Matlab UMTS/LTE Turbo Code

This Matlab code plots the BER, EXIT chart and iterative decoding trajectories for the UMTS and LTE turbo codes, when using BPSK modulation for transmission over an AWGN channel. Functions are provided to generate the UMTS and LTE interleavers, as well as to perform component encoding and decoding. Furthermore, functions are provided for generating a priori LLRs having a particular mutual information, as well as for measuring the mutual information of some LLRs.

main_ber.m draws a BER plot for the UMTS turbo code.
main_exit.m draws an EXIT chart for the UMTS turbo code.
main_traj.m plots the iterative decoding trajectories of the UMTS turbo code.
get_UMTS_interleaver.m provides a function for generating the UMTS interleaver.
component_encoder.m provides an encoder function for the UMTS component codes.
component_decoder.m provides a BCJR decoder function for the UMTS component codes.
jac.m provides a function for performing the exact, lookup-table-aided and approximate Jacobian logarithms.
generate_llrs.m provides a function for generating Gaussian distributed a priori LLRs.
measure_mutual_information_histogram.m measures the mutual information of some LLRs using the histogram method.
measure_mutual_information_averaging.m measures the mutual information of some LLRs using the averaging method.

You can download the Matlab code here. You can also download the LTE interleaver. The operation of the UMTS turbo decoder is described in Section 2.2 of Liang Li’s nine month report and this document.

BER 5000
BER 500
BER 50
EXIT 5000
EXIT 500
EXIT 50

Copyright © 2010 Robert G. Maunder. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

403 Responses to “Matlab UMTS/LTE Turbo Code”

  1. Annena Says:

    Dear Rob,

    In your main_exit.m file in Matlab UMTS Turbo code, the exit chart is based on the figure 2.13. Is this means that the exit chart plotted is only for one decoder? I understand that by swapped the axis, we can display the second curve since the output is the input of the second decoder. I just wonder if we need to repeat the process of figure 2.13 in figure 2.11. If not, the function of interleaver or deinterleaver is not considered, am I right?

  2. Rob Says:

    Hello again Annena,

    In an EXIT chart, each EXIT function depends only on one of the decoders - it is completely independent of the other decoder and of the interleaver. Since the upper and lower codes in a UMTS turbo code are identical, their EXIT functions are also identical. For this reason, there is no need to run two simulations. Instead, you can just take the EXIT function for the upper code and invert its axes to get the EXIT function of the lower code. Please note that while the EXIT functions are completely independent of the interleaver, the iterative decoding trajectories do depend on the interleaver design. The trajectory will only match the EXIT functions if the interleaver is able to randomise the order of the LLRs sufficiently well.

    Hope this helps, Rob.

  3. Annena Says:

    Dear Rob,
    Thank you so much, now I clearly understand. I think, I need to check back the main_traj.m file first.

  4. Annena Says:

    Hi Rob,

    May I know, do you consider channel reliability (Lc) in your BCJR decoding?

    Annena

  5. Annena Says:

    Hi again,

    In case I want to use your component_decoder.m function for different generator, what is the modification should I consider? Is it OK by only changes the trellis matrix?

    Annena

  6. Rob Says:

    Hi Annena,

    In the main_ber.m, main_exit.m and main_traj.m files, I use lines like the following to perform soft BPSK demodulation…
    a_c = (abs(a_rx+1).^2-abs(a_rx-1).^2)/N0;

    If you expand the squares, you can rearrange this to a form including the channel reliability…
    a_c = Lc*real(a_rx);
    … where…
    Lc = -4/N0;

    If you want to change the generator polynomials, all you need to do is change the transitions matrix in component_decoder.m and the equations in component_encoder.m.

    Hope this helps, Rob.

  7. Annena Says:

    Hello Rob,

    I want to know about the main_exit.m file on the encoder part. The data is transmitted using rate 1/2. in the file, you are transmitting systematic bit and parity bit from the first encoder only, right? This means that you did not apply the puncturing method in the encoder.
    Please correct me if I’m misunderstood your program.
    TQ.

  8. Rob Says:

    Hi Annena,

    You are correct. Only the information that is used by the upper decoder is transmitted in this simulation. This allows the upper decoder to be characterised in isolation from the lower decoder. The simulation required to characterise the lower decoder is identical to this one. That is why the results are plotted twice, once for the upper decoder and inverted for the lower decoder. By the way, the UMTS turbo code does not use puncturing.

    Take care, Rob.

  9. Annena Says:

    Hi,
    Tq so much for your help.
    I want to know,

    1. if I run the main_exit.m file using my encoder and decoder, and the result is decreasing for an increasing IA_index, what is it means? I believe it must be something wrong with my program in the decoder part, but is it explain anything?

    2. if we referring to standard parallel concatenated code in paper stephen ten brick fig1, 1st BCJR decoder require input of Z1(systematic and p1) and A1.

    a) If I want to use your main_exit.m file, is it means that A1=a_a?

    b) the length of Z1 is equal to the length of (a_c+c_c + e_c(terminated bits)). Since a_a is generated from a, which is without terminated bits, the length of a_a is not equal to Z1. If A1=a_a, can I just add bit zeros to a_a so that it will have the same length as Z1?

    I’ll really appreciate your help.

  10. Rob Says:

    Hi Annena,

    1. It sounds like there is a problem with either your encoder or your decoder. You can confirm this by comparing the EXIT functions that you get using the averaging method of measuring mutual information with the EXIT functions you get using the histogram method. If these EXIT functions are significantly different then it implies that there is a bug in your encoder, modulator, demodulator or your decoder.

    2a. That’s right. Here, I’m assuming that you mean this paper…
    http://scholar.google.co.uk/scholar?cluster=15764897033271139190&hl=en&as_sdt=2000

    2b. Note that the length of A1 is not equal to the length of Z1 in that paper - it is half the length of Z1. The operation of main_exit, main_ber and main_traj is illustrated in Figures 2.11 and 2.13 of…
    http://users.ecs.soton.ac.uk/rm/wp-content/liang_li_nine_month_report.pdf
    Here, if the interleaver has a length of N bits, then a_c has a length of N, c_c and d_c have lengths of N+3, while e_c and f_c have lengths of 3. Instead of zeros as you suggest, e_c is concatenated onto a_a+a_c in order to give y_a, which has the same length as c_c of N+3.

    Hope this helps, Rob.

  11. Annena Says:

    Hi Rob,

    Thank you so much for your help, I feel so happy because finally I manage to plot my first EXIT chart using my encoder and decoder.
    Now, I’m learning to plot the trajectory part.
    1) May I know, why is the file main_traj.m plot trajectory at different frame? Should we just average the value so that we can get just a smooth trajectory plot?
    2) From the trajectory figure, can we plot the EXIT curve by taking the peak of each trajectory point or do we need to map it into figure from main_exit.m?

    Really appreciate your help.

    Regards,
    Annena

  12. Rob Says:

    Hi Annena,

    1) You can average the trajectories, but you sometimes find that the result doesn’t give a very good match with the EXIT functions. Also, if you take the average of the trajectories, you don’t get a feel for how much variation there is from frame to frame. It is this variation that explains why short frame lengths give a poorer performance than longer frames.
    2) You can do this, but the result will typically not be very smooth and will also depend on your interleaver design. Furthermore, the whole point of EXIT chart analysis is that is can be done without requiring lengthy iterative decoding simulations.

    Hope this helps, Rob.

  13. Annena Says:

    Hi Rob,

    I noticed that your BPSK encoder modulate the bit 1 to -1 and the bit 0 to 1. In your component_decoder.m file, extrinsic_uncoded_llrs(bit_index) = prob0-prob1, does it mean prob0 is for bit 1 and prob1 is for bit -1? in case I modulate it otherwise, 1–> 1 and 0 –>-1, can I still used your decoder file?

    Appreciate your advise.

  14. Rob Says:

    Hi Annena,

    I find that this causes a lot of confusion for people. It all comes down to whether LLRs are defined as LLR=ln(P0/P1) or LLR=ln(P1/P0). J Hagenauer uses the former definition and C Berrou uses the latter one. My code uses the definition LLR=ln(P0/P1). If another part of your system uses the other definition (such as your BPSK demodulator), all you need to do is multiply your LLRs by -1 when you pass them from part of the system to the other.

    Hope this helps, Rob.

  15. Mila Says:

    Hi Rob,

    I develop my own encoder file where only my first encoder is terminated and the second encoder is not. To develop the decoder, how can I modify your component_decoder.m file?
    Please advise.

    TQ

  16. Rob Says:

    Hi Mila,

    All you need to do for the unterminated decoder is change the line…
    betas(1,length(apriori_uncoded_llrs))=0;
    …to…
    betas(:,length(apriori_uncoded_llrs))=0;

    Take care, Rob.

  17. Mila Says:

    Hi Rob,

    Thank you for your respond.

    May I know, is it possible to plot the EXIT chart using your function when the first decoder is terminated and the second decoder is not?
    As I know, for parallel turbo code, we only used one decoder only to plot the EXIT chart.
    Please advise

    TQ

  18. Rob Says:

    Hi Mila,

    You should fnd that termination makes only a negligible difference to the EXIT function, particularly if you have a long interleaved. My advice would be to simply mirror one or other of the EXIT functions - either the terminated one, or the unterminated one.

    Take care, Rob.

  19. Lai Says:

    Hi Bob,

    1. Thank you so much for your code. It is really hard to find something so helpful about the BCJR algorithm in MATLAB on the Internet.

    2. I have a question. Now I want to implement a conv code decoder with BCJR based on your code, but in my scenario the rate of the code is different, like 2/3.
    (1) Are the equations in Liang Li’s report still applicable?
    (2) I know I need to change the “transitions” matrix; for the “UncodedBit” and “EncodedBit” column, do I need to expand them into several binary column, or simply use decimal representations of the bits, such as 7 for 111?
    (3) Other things I need to care about?

    Thank you very much for your help.

  20. Rob Says:

    Hello Lai,

    The equations in Liang Li’s report are still applicable, but they need to be generalized. You can see generalized versions at…
    http://users.ecs.soton.ac.uk/rm/wp-content/LogBCJR.pdf
    You need to insert an additional column into the transitions matrix for each additional input and output bit. For example, a k=2, n=3 CC would have a transitions matrix with 7 columns: two for the states, two for the input bits and three for the output bits. You also need five sets of gamma calculations, one for each input and output bit. Finally, you need two sets of gamma and extrinsic LLR calculations, one for each input bit.

    Hope this helps, Rob.

  21. Rob Says:

    Somebody has asked me how to concatenate the UMTS turbo decode with an additional inner decoder, such as a SISO MIMO detector. I have drawn a schematic for this and uploaded it to…
    http://users.ecs.soton.ac.uk/rm/wp-content/concat.png

    Take care, Rob.

  22. José Says:

    Hi Rob,

    Fine algorithm, I’ve been using it to run some tests within a larger system. However, ECC are not my domain and I need to obtain the LLRs of the coded bits (lc+ld+le+lf) and not just the LLRs from the data bits (la) at the end of the turbo decoding step. Howmay I achieve it? Thanks in advance.

  23. Rob Says:

    Hi José,

    This is not too difficult to achieve. You just need to modify component_decoder.m so that it has an additional output called extrinsic_encoded_llrs. You can generate this using these lines of code

    % Calculate encoded extrinsic transition log-confidences. This is similar to
    % Equation 2.18 in Liang Li’s nine month report or Equation 4 in the BCJR paper.
    deltas2=zeros(size(transitions,1),length(apriori_encoded_llrs));
    for bit_index = 1:length(apriori_encoded_llrs)
    for transition_index = 1:size(transitions,1)
    deltas2(transition_index, bit_index) = alphas(transitions(transition_index,1),bit_index) + uncoded_gammas(transition_index, bit_index) + betas(transitions(transition_index,2),bit_index);
    end
    end

    % Calculate the encoded extrinsic LLRs. This is similar to Equation 2.19 in
    % Liang Li’s nine month report.
    extrinsic_encoded_llrs = zeros(1,length(apriori_encoded_llrs));
    for bit_index = 1:length(apriori_encoded_llrs)
    prob0=-inf;
    prob1=-inf;
    for transition_index = 1:size(transitions,1)
    if transitions(transition_index,4)==0
    prob0 = jac(prob0, deltas2(transition_index,bit_index));
    else
    prob1 = jac(prob1, deltas2(transition_index,bit_index));
    end
    end
    extrinsic_encoded_llrs(bit_index) = prob0-prob1;
    end

  24. José Says:

    Hi Rob,

    Thanks for your help, it works just fine. Much apprettiated.

  25. swap Says:

    Dear Rob

    Can you plase tell somthing about turbo codes, that as why is it necessary that the information feeded into encoder should be unocrrelated as much as possible.

    What if they are correlated, apart from turbo decoding how does it affect. Can you please explain it

    thanks
    swap

  26. Rob Says:

    Hi Swap,

    If the occurrence of two events A and B is correlated then their joint probability is given by P(A,B) = P(A|B)*P(B). If they are uncorrelated then the joint probability is given by P(A,B) = P(A)*P(B). The second situation is much easier to work with because we only need one P(A) value for each outcome of A. By contrast, the first situation requires a P(A|B) value for each possible combination of outcomes of A and B. To save on complexity, the BCJR assumes that P(A,B) = P(A)*P(B), i.e. that the LLRs are uncorrelated. If they are correlated, then this assumption is false and the performance of the BCJR suffers.

    Take care, Rob.

  27. Mory Says:

    Hi Rob,

    First of all, thanks for the code, it’s really helpful. For component turbo code, you have separated the information, parity as well as the termination bits when input to channel. I wonder whether the result will be the same if they are combined into one before input to the channel?

    The reason for me asking the question because I’m not sure whether the Randn function in Matlab is independent statistically when you call it for the second or subsequent time. Let say it’s independent, therefore for your case, the AWGN noise is independent for each the systematic, parity and termination sequence (a_rx,c_rx_d_rx,e_rx and f_rx)?

    Looking forward for your explanation.

    Many Thanks,
    Mory

  28. Rob Says:

    Hi Mory,

    I kept the different bit sequences separate because it is very easy to make a mistake when programming their concatenation and de-concatenation. If they were concatenated, all the results would be exactly the same.

    Take care, Rob.

  29. Colin O'Flynn Says:

    Hello,

    Thanks for your great work & handy reference. I think I found a tiny typo/bug in the code: in main_exit.m, the value 0.3037 should be 0.3073 ( from http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=1499068 ).

    Regards,

    -Colin

  30. Rob Says:

    Hi Colin,

    Thank you for this. However, I’m not sure where in my code or the paper you mean - I can’t find any values of 0.3037 or 0.3073 in my code or that paper.

    Take care, Rob.

  31. Colin O'Flynn Says:

    oops… I meant generate_llrs.m

  32. Rob Says:

    Hi Colin,

    Thanks for noticing this typo - I have updated all the occurrences of this mistake in the code on my website (I think). This shouldn’t make any difference to the results though, because of the while loop in generate_llrs.m.

    Take care, Rob.

  33. Lingjun Says:

    Dear Rob,

    I have some questions in component_decoder.m,

    why there are two parts: uncoded_gammas and encoded_gammas, while in bcjr_decoder is just gammas . And why uncoded_gammas is computed in alphas and betas,but not deltas. By the way , in the computaion of alphas or betas , why the bit_index -1 is used ?(encoded_gammas(transition_index, bit_index-1)) Many thanks.

  34. Lingjun Says:

    alphas(transitions(transition_index,2),bit_index) = jac(alphas(transitions(transition_index,2),bit_index),alphas(transitions(transition_index,1),bit_index-1) + uncoded_gammas(transition_index, bit_index-1) + encoded_gammas(transition_index, bit_index-1));
    Based on equ. 5 in BCJR , uncoded_gammas(transition_index, bit_index) + encoded_gammas(transition_index, bit_index). Is it right?

    But I don\’n understand why just the encoded_gammas is used to compute the deltas in component_decoder and both encoded_gammas and uncoded_gammas are used in bcjr. Wait for your answer . Thanks a million.

  35. lingjun Says:

    Dear Rob,
    In main_ber :a_p = a_a + a_c + a_e;
    In main_traj :a_p = a_a + a_e;

    So why not the same?

  36. Rob Says:

    Hi Lingjun,

    This is the difference between a BCJR decoder that generates extrinsic LLRs and one that generates aposteriori LLRs. A decoder that generates aposteriori LLRs has the advantage of not needing to make a distinction between uncoded_gammas and encoded_gammas, therefore giving a lower complexity. However, there is a small disadvantage, which relates to the fact that the extrinsic LLRs must be calculated by subtracting the aproiri LLRs from the extrinsic LLRs - if the apriori and extrinsic LLRs are both infinite in magnitude, then subtracting one from the other gives an undetermined result. This is a very minor disadvantage and so in practice, decoders that generate aposteriori LLRs are preferred, owing to their lower complexity.

    By the way, the line a_p = a_a + a_e; in main_traj.m should say a_p = a_a + a_c + a_e; I have fixed this bug and uploaded a new version of the code.

    Take care, Rob.

  37. Ideal Says:

    Dear Rob,

    I want to implement puncturing using LDPC code in two parallel (AWGN) channels. I have the concept of puncturing but I am feeling difficulties in implementing.

    could you suggest me any help in this matter please please

  38. Rob Says:

    Hi Ideal,

    To puncture a bit sequence, you just remove some of the bits in the transmitter. To perform the corresponding depuncturing operation in the receiver, you just replace the punctured bits with zero-valued LLRs.

    Take care, Rob.

  39. Ideal Says:

    Hi Rob,

    That is possible for single channel. Actually I want to implement the puncturing in two channel (parallel optical and RF channel).

    I think there would be a way to generate a puncturing pattern using single encoder/decoder.

    I can assume the channel state information at the transmitter and can puncture the codeword accordingly but what can be the ensemble and how to send the punctured bits in different channel is a challeng for me. Thats why I am looking such a technique which can give me inside help about the puncturing. Thanks

  40. Rob Says:

    Hi Ideal,

    I think that you are entering new ground with what you are talking about and so I think that you will have to investigate how best to do the puncturing yourself.

    Take care, Rob.

  41. Ideal Says:

    Hi Rob,

    I got few ideas but one thing,

    If i puncture some bits at the trasmitter side then for the depuncturing on the receiver side, how can I add zeros at the exact locations, i.e.
    let x= [1 0 1 1 1 1 0 1] is a codeword and I puncture either random or few bits from x.

    let few bits punctured xp = [p 0 1 1 1 p 0 p], it means i puncture 1, 6 and 8 bit, how the receiver knows about it, I mean in matlab how can I write a command for this.

    secondly If I have a (half rate, r=0.5) codeword of length 1024 and I punctured 171 bits randomly out of 1024 to have a rate of rp=0.6. now how can i introduced zeros at the particular values of punctured codeword.

    The simple question is in random puncturing, how can i write a command in matlab which can puncture the bits at the transmitter and add zeros at those locations (punctured) at the reciever side. please send me this type of matlab script please. thanks

  42. Rob Says:

    Hi Ideal,

    The receiver needs to have knowledge of the puncturing pattern. This code does everything you are talking about - it also interleaves the bits, which is useful in a Rayleigh fading channel.

    temp = randperm(1024);
    pattern = temp(1:853);

    % In the transmitter
    punctured_bits = bits(pattern);

    % In the receiver
    llrs = zeros(size(bits));
    llrs(pattern) = punctured_llrs;

    Take care, Rob.

  43. Ideal Says:

    Dear Rob,

    I really very much appreciate your help.

    one things more please,

    1. bits are the coded bits after the encoder?
    2. In line, llrs(pattern) = punctured_llrs; you didn\’t defined punctured the punctured_llrs, I think, punctured_llrs = (2/sigma^2)*(punctured_bits + noise); for awgn channel?

    Am I right in the above two questions?
    Again I am really very appreciate your help. Thanks

  44. Rob Says:

    Hi Ideal,

    Both of your assumptions are correct.

    Take care, Rob.

  45. Ideal Says:

    Dear Rob,

    Thanks for the answer, One more question please :)

    I just want to understand the concept of capacity approaching low density parity check codes, (some researcher are calculating the bit error rate curve for certain LDPC code and claim that its capacity approaching code)

    can you have any suggestion/advise for that things?

    Thanks for that

  46. Rob Says:

    Hi Ideal,

    You should look into Irregular LDPC codes - these can operate extremely closely to the Shannon capacity.

    Take care, Rob.

  47. Ideal Says:

    Dear Rob,

    Currently I am interested in low rate regular structure LDPC code and then introduce ouncturing to in increase the code rate. using simple bpsk channel.

    But I am confuse with the threshold of code and capacity. Like I don’t understand, how to calculate the threshold of the code and how to prove that it is capacity approaching code for simple BPSK AWGN channels and even the punctured code with higher rate is performed well. These are the questions I have in my mind please :)

    Thanks for the response

  48. Rob Says:

    Hi Ideal,

    You can draw the EXIT chart of your LDPC codes and find the lowest SNR at which the EXIT chart tunnel remains open. Then, you can compare this SNR with that at which the capacity of the channel becomes equal to the throughput of your LDPC code. If the SNRs are similar, then your code is a near-capacity code.

    Take care, Rob.

  49. Ideal Says:

    Dear Rob,

    Thanks now I understand the threshold. Thanks

    What is the relation between the throuhgput of LDPC code and the channel capacity (sorry for silly questions).

    According to me, throughput = symbol rate x capacity, but I am not sure, how to calculate the throughput of LDPC code and compare with channel capacity?

    I can calculate the EXIT chart, bpsk channel capacity but not sure how to compare the throughput of LDPC code with channel capacity at particular snr?

    Thanks for help

  50. Rob Says:

    Hi Ideal,

    The throughput is measured in bits per symbol (or equivalently bits per second per hertz) - it is given by R*log2(M), where R is the LDPC coding rate and M is the number of constellation points in your modulation scheme, e.g. M=16 in 16QAM. The capacity is plotted at http://users.ecs.soton.ac.uk/rm/resources/matlabcapacity/

    Take care, Rob.

  51. Ideal Says:

    Dear Rob,

    I understand the calculation of capacity. Thanks

    I understand the threshold will be that value of snr where the check node curve and the variable node curve just touches.

    Also As we know that I_A = J(sigma), where sigma = sqrt(8*R*Es/No)?

    sorry for not getting the point

    1. EXIT chart (snr) = threshold (where two curves touches)
    2. channel capacity (snr(Threshold)),

    you said (Then, I can compare this SNR(threshold) with that at which the capacity of the channel becomes equal to the throughput (R*log2(M) of your LDPC code. If the SNRs are similar, then your code is a near-capacity code.)

    It means for half rate code and bpsk modulation, the LDPC throughput will be 0.5. Then for the near capacity code, the channel capacity of bpsk channel should be near 0.5 at snr(threshold). I think I am right now :)

  52. Rob Says:

    Hi Ideal, You’ve got it. Rob.

  53. Ideal Says:

    Dear Rob,

    Can you please tell me any code of generating the ldpc parity check matrix (H) and the corresponding generator matrix (G).

    I know about the PEG algorithm for generating H matrix but I want some other script if you know please. Thanks

  54. Ideal Says:

    DEAR ROB,

    IS THERE ANY EASY WAY TO CALCULATE THE DECODER TRAJECTORY (STAIRS) IN MATLAB? THANKS

  55. Rob Says:

    Hi Ideal,

    I have uploaded some code for generating G and H matrices to…
    http://users.ecs.soton.ac.uk/rm/wp-content/generate_H.m
    The trouble with this code is that it tries too hard to find matrices that have exactly the specified degrees, and so it takes a long time to run. You should probably modify it to make it quicker to run.

    You can download main_traj.m from the top of this page - it shows you how to plot the trajectory.

    Take care, Rob.

  56. Ideal Says:

    Dear Rob,

    Its really great help. I will look in the code. Thanks dear Sir,

  57. Elnaz Says:

    Hi Rob,

    I’m trying to use your BCJR to decode my 1/3 Turbo coded stream.
    I don’t understand the way you’re calculating “gammas” (Equation 2.14 in the 9 month report). Specificly, how you derive that (1-y(t)) .. formula and why don’t you directly use the conditional pdf instead? Is this specific to UMTS code?
    Could you please explain?

    Thanks,
    Elnaz

  58. Elnaz Says:

    Hi Rob,

    I have another question:
    In calculating “betas”, according to the report you cited, shouldn’t we calculate each “betas” using the “gammas” value of the same stage i.e. to follow backward recursive move? In your code you are using the “gammas” value for the next stage. Am I missing something here?
    I see the same thing when you caculate “deltas” i.e. “alphas” and “gammas” and “betas” are all indexed with “bit_index” but I think “betas” should be indexed by “bit_index”+1 (one stage ahead).

    Thanks,
    Elnaz

  59. Ideal Says:

    Dear Rob,

    I try to understand the code of main_traj.m but couldn’t. I am using the LDPC code and its trajectory will be the information exchange between the variable and check nodes. So i think there should be simple program in order to calculate the trajectory without using the sum-product algorithm.

    At the moment I am using the Sum-Product algorithm and calculating the trajectory based on the information exchange when the SP algorithm runs. I was thinking to calculate the trajectory without running the decoder. I am not sure if it is possible? Thanks

  60. Rob Says:

    Hi Ideal,

    If you have the EXIT chart then it is possible to predict the trajectory, without running the iterative decoder. You just need to manually draw a staircase that bounces between the two EXIT functions. The trouble is that this predicted trajectory will only be valid in the case of a very long block length. This approach will not let you consider the variation in the trajectory that results when using shorter block lengths.

    Take care, Rob.

  61. Rob Says:

    Hi Elnaz,

    Equation 2.14 is saying that if a transition is labelled with a zero, then the corresponding gamma should take on the value of the corresponding a priori LLR. If the transition is labelled with a one, then the corresponding gamma should take on the value of zero.

    This approach has a slightly lower complexity than the one originally proposed for the Log-MAP. This says that if a transition is labelled with a zero, then the corresponding gamma should take on the value of the corresponding a priori LLR divided by 2. If the transition is labelled with a one, then the corresponding gamma should take on the value of the corresponding a priori LLR divided by -2.

    Betas should be calculated using the gammas of the transitions to the right of the corresponding states. I think that the notation in the original explanation of the Log-MAP may be confusing you. It is because this notation is so confusing that we decided to explain things in this different way.

    Take care, Rob.

  62. Elnaz Says:

    Hi Rob,

    Thanks for your explanation.
    As for my first question, I don’t see you divide LLRs by 2? The way I explained it to my self is that you’re normalizong LLRs with respect to the probability of a bit value being 1 and zero (if you know what I mean).

    Actually, this brings another question because in this normalization you have LLR= P(bit=1)/P(bit=0), but at the end of the program you calculate extrinsic LLR with P(bit=0)/P(bit=1) ratio?

    Also, why are you omitting “uncoded-gammas” in calculating “deltas” ?

    Thank you for answering my questions,

    Elnaz

  63. Rob Says:

    Hi Elnaz,

    There’s no need to dived by two if you do it the way I do here - this is because the absolute value of the gammas doesn’t matter - it’s the difference between the gammas associated with one and zeros that matters.

    I think that I’m using LLR=ln(p0/p1) throughtout this code, but I’ll check this.

    The reason why uncoded_gammas is omitted from the delta calculation is because this causes the algorithm to generate extrinsic LLRs directly, rather than a posterior LLRs.

    Take care, Rob.

  64. Elnaz Says:

    Thanks Rob,

    So for the “gammas” to take the value of LLR when input bit is zero, we should have: P1 = 1/(1+exp(LLR)) and P0= exp(LLR)/(1+exp(LLR)) which means LLR is log(P1/P0). Because with this we’ll have log(P1) = -log(1+exp(LLR)) and log(P0) = LLR - log(1+exp(LLR)) where by omitting the common term we’ll end up with what you do in the code. Is this correct?

    Another point of confusion for me is where in calculating “deltas” you’re using “bettas of bit_index” while according to text books we should use the next stage “betas” here. Shouldn’t we?

    Thanks,
    Elnaz

  65. Rob Says:

    Hi Elnax,

    Actually, P1 = 1/(1+exp(LLR)) and P0= exp(LLR)/(1+exp(LLR)) implies that LLR = log(P0/P1), not LLR = log(P1/P0).

    To put the calculation into words for you, the delta of a transition is equal to the sum of
    * the encoded gamma of that transition,
    * the alpha of the state that the left end of the transition connects to and
    * the beta of the state that the right end of the transition connects to.
    This is what the text books say, although they often use confusing notation to do it.

    Take care, Rob.

  66. Elnaz Says:

    You’re right; maybe the original explanation of the Log-MAP is confusing me. I think there is only one “gammas” for each transition between two states, however, the direction of movement changes in calculating “alphas” vs. “betas”. For example, gammas of 1 changes the state from 1 to 2. In calculating bettas of 1, I think, we should do: (Bettas of 2) X (gammas of 1) not (gammas of 2) because gammas of 2 takes state 2 to state 3. But, you’re doing the gammas of 2 in the code!

    Elnaz

  67. Rob Says:

    Hi Elnaz,

    I’m afraid I’m not sure what you mean here. You should note that the gamma and delta values correspond to particular transitions. By contrast, the alphas and betas correspond to particular states. I’d encourage you to look closer at the code - I’m quite confident that there is no mistake in it.

    Take care, Rob.

  68. Elnaz Says:

    Hi Rob,

    Surely, the code is correct. I’m trying to resolve my points of confusion which is partly the way you’re indexing “gammas” in calculating “betas”. In my previous note I wrote one of the iterations in your nested loops (where you calculate “betas”). So, for example you get bettas(..,bit_index=1) from betas(…, bit_index=2) (next state) and gammas(…, bit_index=2). My confusion is that I think it should be using gammas(…, bit_index=1) instead of gammas(…, bit_index=2) because it is gammas(…, bit_index=1) that takes us from stage 1 to stage 2. gammas (…, bit_index=2) will take us from stage 2 to stage 3.
    Did I succeed explaining what I don’t understand?

    Thanks,
    Elnaz

  69. Rob Says:

    Hi Elnaz,

    I see what you mean now - you are looking at the following line…
    deltas(transition_index, bit_index) = alphas(transitions(transition_index,1),bit_index) + encoded_gammas(transition_index, bit_index) + betas(transitions(transition_index,2),bit_index);

    Since bit_index is the same for alphas and beta, it looks like the states that correspond to these are in the same horizontal position within the trellis. If you look closely though, you’ll see that bit_index refers to a transition’s horizontal position, not a state’s horizontal position. I’ve set things up so that a particular value in alphas corresponds to a state at the left end of the transition indexed by bit_index. By contrast, betas is set up so that each of its values corresponds to a state at the right end of the transition indexed by bit_index.

    Take care, Rob.

  70. Elnaz Says:

    Hi Rob,

    Actually, I’m referring to where you calculate “betas”, line:
    betas(…, bit_index) = jac(betas(…, bit_index),betas(…, bit_index+1) + uncoded_gammas(…, bit_index+1) + encoded_gammas(…, bit_index+1));

    I think we should have:

    betas(…, bit_index) = jac(betas(…, bit_index),betas(…, bit_index+1) + uncoded_gammas(…, bit_index) + encoded_gammas(…, bit_index));

    Because it is gammas(…, bit_index) that moves us horizontally from bit_index to bit_index+1 position in trellis.

    According to text books:

    Beta (stage=k, state=p) = sum over different states of (gamma(stage=k, state=p to state=q) * Beta(stage=k+1, state=q).
    i.e. in calculating beta in stage=1(horizontal position in trellis) we use beta of the position to the right (next stage, stage=2) and gammas of the same position (same stage, stage=1) which takes us from stage=1 to stage=2. Translating this to your code, it means we should use gammas(…, bit_index) instead of gammas(…, bit_index+1).

    Elnaz

  71. Rob Says:

    Hi again Elnaz,

    Taking my previous reply a step further, betas(…, bit_index) refers to a state that is to the left of the transition referred to by uncoded_gammas(…, bit_index+1). Similarly, betas(…, bit_index+1) refers to a state that is to the right of that transition.

    Take care, Rob.

  72. Elnaz Says:

    I see that Rob; and that is exactly my point of confusion because there is only one gammas for each transition and we use it in calculating both betas and alphas.
    The way you calculate alphas exactly matches with text book but betas does not. What makes it confusing to me is that we use say gammas(…, bit_index=2) to to go from betas(…, bit_index=2) to betas(…, bit_index=1)!
    I’m sorry it seems I’m repeating my question here but it seems to me that each transition is marked with one gamma only and in the code we’re referring to the same transition by different gammas when caculating alphas versus betas.

    Thank you,
    Elnaz

  73. Rob Says:

    Hi Elnaz,

    That’s right - the gammas used for the alpha calculations are the same as the ones used for the beta calculations. The only difference between alpha calculations and beta calculation is that the former uses a recursion from left to right, while the latter uses a recursion from right to left.

    Take care, Rob.

  74. Elnaz Says:

    Yes, exactly! So when we move from time k (bit_index=k) to time k+1 (bit_index=k+1) in the trellis, we’re marking this transition with gammas(…, bit_index=k). Now, here, we move to the right from alphas(…, k) to alphas(…, k+1) and move to the left from betas(k+1) to betas(k) on the same transition marked with gammas(..,k).
    The question is you’re not doing the above thing in the code. you have alphas(…,k+1) and betas(…, k) referring to the same node i.e. the same point in time!
    This is where I don’t get it!

    Elnaz

  75. Rob Says:

    Ah, but you are assuming that alphas and betas are using the same time reference - i.e. that alphas(…, bit_index) and betas(…, bit_index) are referring to the same state. Actually the state that alphas(…, bit_index) refers to is one position to the left of the state that betas(…, bit_index) refers to.

    Take care, Rob.

  76. Elnaz Says:

    Thank you Rob. I get it now. It is just the way you name your betas. I was thinking your theory may be different which is not.

    Actually, I want to use two BCJR decoders, parallely concatenated, to decode a rate 1/3 Turbo code. I know that I should pass the output of each decoder (function here) as the apriori_uncoded_llrs input to the other function and iterate in a figure 8 shape. But where should I use the systematic output of the channel? I can’t feed both systematic and parity streams to the decoder function.

    Thank you,
    Elnaz

  77. Rob Says:

    Hi Elnaz,

    Take a look at Figure 2.11 in the nine month report. The systematic LLRs can be added to the interleaved extrinsic LLRs.

    Take care, Rob.

  78. Anna Says:

    Hi Rob,

    I learned many thing just reading the above questions and answers, so thanks for that.

    I just have a small question about puncturing LDPC codes.

    In my matlab script, I puncture a portion of the information bits in a systematic codeword in the transmitter side.
    My problem is with the receiver side. In an earlier comment you have mentioned that I need to replace the puncture bits with zero-valued LLR values. Did you mean the LLR values from the channel to the variable node which is use to generate the apostiriori LLR values?

    Even thoug I perform the above, I get a BER curve exactly as that for a LDPC code without puncturing. Really appreciate if you can explain this to me.

    Thanks in advance.

  79. Rob Says:

    Hi Anna,

    Yes, I mean the LLRs from the channel to the variable nodes. I can’t think why your BER plot stays the same when you introduce puncturing - puncturing should degrade the performance. It sounds like you think you are puncturing the bits, but actually you are still transmitting them…

    Take care, Rob.

  80. Rob Says:

    Elnaz says…
    “Hi Rob,

    I am using two BCJR decoders, parallely concatenated, to decode a rate 1/3 turbo code. As you said earlier, I am adding the systematic LLR to the output of one decoder and feed them as apriori_uncoded_llr to the other decoder.

    My question is with BER plot where I add a variance \"sigma2\" noise (\"randn\" command) to my sequence and simply plot the error rate vs. (Eb=1)/(2*sigma2). However, with small sigma2 values (smaller than 1.3), the waterfall discontinues and a series of up and down fluctuations begins. Fluctuations are about BER = 10^-4. Why this is happening?

    Thank you,
    Elnaz”

    Hi Elnaz,

    It may be that you have reached the error floor of your turbo code. The position of your error floor will depend on the design of your turbo code. In particular, it will depend on your interleaver length. An error floor of 10^-4 suggests to me that your interleaver length is quite small - does this sound correct to you?

    Take care, Rob.

  81. Elnaz Says:

    Hi Rob,

    Thanks for your answer.
    I am interleaving the whole sequence (about 4000 bits) at once with Matlab\’s \"randintrlvd\". What do you think?

    Elnaz

  82. Rob Says:

    Hi Elnaz,

    That sounds okay to me. I normally use Matlab’s randperm function though…

    interleaver = randperm(4000);
    interleaved_bits = bits(interleaver);
    deinterleaved_bits(interleaver) = interleaved_bits;

    Take care, Rob.

  83. Elnaz Says:

    Yes, Rob; doing exactly like above, the fluctuations around 10^-3 remain to be. They are happening with SNRs higher than -5 dB.

  84. Rob Says:

    Hi again Elnaz,

    My advice would be to try using a 10-times longer interleaver length, to see how that affects things.

    Take care, Rob.

  85. Elnaz Says:

    Hi Rob,

    Can it be longer than the whole data length? Currently I am using
    interleaver = randperm(4000); which covers my whole data length (entire stream of original bits).
    Do you mean to somehow zero-pad the data?

    Thanks,
    Elnaz

  86. Ideal Says:

    Dear Rob,

    I was studying the paper \"Analysis of low-density parity-check codes based on EXIT functions\" by Sharon, E. \"Communications, IEEE Transactions on\". It was describing the EXIT trajectories in very good ways.

    I tried to implement the EXIT trajectory using the update rules in equations (8,9,10), but I couldn\’t. Is anyone can implement these trajectory rules update for me please?

    In this way, it is easy to calculate the trajectories. Thanks :)

  87. Rob Says:

    Hi Elnaz,

    I would suggest to repeat your 4000-bit message ten times, to create a 40000-bit message.

    Take care, Rob.

  88. Rob Says:

    Hi Ideal,

    It is Equations 11 and 12 from that paper that you should use to draw the EXIT functions and trajectories.

    Take care, Rob.

  89. Ideal Says:

    Dear Rob,

    You are right, Equation 11 and 12, we can get the extrinsic mutual information for the variable node using 11 and we can get the extrinsic mutual information for the check node using equation 12.
    But how can we plot the trajectory curve (stair curve). I don’t understand the trajectory curve. I can plot the variable node curve and check node curve but can’t able to plot the trajectory.

    Secondly, Is the trajectory curve plot will also be same with the puncturing scheme? Thanks, I am asking so many questions, but I learn a lot with your supervision. Thanks

  90. Rob Says:

    Hi Ideal,

    You need to use Equation 11 and 12 alternately. You start with an input MI of zero, then use the output MI of each equation as the input to the other. This process is the same whether you use puncturing or not.

    Tae care, Rob.

  91. Elnaz Says:

    Hi Rob,

    Even with increasing the length to 40000, it still jumps around 10^-4, not much of an improvement I guess. Could you guide me as to what is the standard basis of BER floor in a 1/3-rate Turbo decoder?
    I don\\\’t know if 10^-4 is normal or there is something wrong with my code.

    Thanks,
    Elnaz

  92. Rob Says:

    Hi Elnaz,

    It sounds to me like you have a problem with a few bits in each frame. This suggests to me that there may be a problem with the way you are terminating the trellis. Perhaps you are not using termination in the encoder, but your decoder assumes otherwise…

    Take care, Rob.

  93. Elnaz Says:

    Hi Rob,

    Actually, for the encoding part, I am the same encoder twice, once with systematic output and once without that:

    trellis1 = poly2trellis(3,[7 5],7);
    code1 = convenc(msg,trellis1);
    Then I interleave:
    intrlvd = msg(interleaver);
    trellis2 = poly2trellis(3,5,7);
    code2 = convenc(intrlvd,trellis2);

    Using convenc, do I have control over termination?
    After this I am using your BCJR decoder in a turbo-decoder and decode the whole stream at once (not frame-by-frame).
    Could you please explain more as to what you mean by \\"decoder assumes otherwise…\\"?

    Thanks,
    Elnaz

  94. Elnaz Says:

    Hi Rob,

    Let me add this: in high SNRs I am having, as you said, a few bits of error.
    Also, in my turbo decoder, I initialize the extrinsic LLR of the 2nd decoder with zeros before iterations start.
    Does this mean that the encoders should be in state zero at the end of the stream? If yes, how can I force them to zero state while using \"convenc\". I appreciate if you could clarify this for me more.

    Thanks,
    Elnaz

  95. Rob Says:

    Hi Elnaz,

    I think my suspicion is correct. I don’t think that convenc uses termination. You can stop my component_decoder.m from using termination by changing the line…
    betas(1,length(apriori_uncoded_llrs))=0;
    …to…
    betas(:,length(apriori_uncoded_llrs))=0;

    As you say, termination forces the encoder into the state zero at the end of the stream. If you want to achieve this using convenc, I think you will need to add some additional bits to the end of your message, as in the UMTS turbo encoder.

    Take care, Rob.

  96. Ideal Says:

    Dear Rob,

    Thanks for reply, I have one more question please.

    In the capacity approaching codes, we usually compare the SNR_threshold of LDPC code with the corresponding channel capacity.

    I found the channel capacity equation is the J function, i.e., C = J(sigma_ch), where the sigma_ch = sqrt(8 * R * Eb/No).

    my question is that the equation I wrote is OK to compare with the SNR_threshold, if yes, then what should be the value of R? It will be the mother code rate or not? Thanks

  97. Elnaz Says:

    Hi Rob,

    Changing the code, as you said, nulled out the error at high SNRs; Now I have zero errors at high SNRs. But BER still doesn’t fall smoothly. For example, with #iterations=20, it sharply falls from 10^-2 to -inf. And, with #iterations=2 it fluctuates between 10^-4 and -inf (step size is very small). I never see 10^-6, 10^-7 or…
    Let me add that, here, since I just want to test the decoder, I only encode, then add noise, then decode. I’m thinking maybe this is causing that since I’m not doing any modulation and all.
    Do you think the decoder is what it should be? Is not using termination causing this?

    Thanks a lot,
    Elnaz

  98. Rob Says:

    Hi Ideal,

    I’m not sure where you have got that relationship between the channel capacity and J function from - I’m not sure that you can use it in this context. Presumably, you are trying to quantify the BPSK DCMC capacity. I would suggest doing this using the code at…
    http://users.ecs.soton.ac.uk/rm/resources/matlabcapacity/

    Take care, Rob.

  99. Rob Says:

    Hi Elnaz,

    What you are describing sounds like a steep turbo cliff, which is usual for turbo codes. I think that the reason why you cannot observe low BERs is because your simulation is not long enough. To observe a BER of 10^-7, you need to be transmitting 10^9 or 10^10 bits, which requires a very long simulation (perhaps taking one week to run).

    Take care, Rob.

  100. Ideal Says:

    Dear Rob,

    I got it the plot of channel capacity vs the coding threshold. Thanks again.

    I am a bit poor in writing tricky MATLAB code. Like about the EXIT trajectory, You gave the idea that the two equations are used alternatively and in this way the information stairs end up at (1,1) but when I start writing the code, I am facing problem. Can you please give me a bit clue please. :) Thanks

  101. Rob Says:

    Hi Ideal,

    Something like this should do the trick…

    IA = 0;
    IE = 0;
    results = [IA,IE];
    for iteration_index = 1:100
    IE = variable_node(IA);
    results = [results; [IA,IE]];
    IA = check_node(IE);
    results = [results; [IA,IE]];
    end
    plot(results(:,1), results(:,2);

  102. sowmya Says:

    dear rob,
    i want to test an image transmission over wireless sensor network using turbo codes can this be done using the code …?

    THANK YOU

  103. Rob Says:

    Hi Sowmya,

    This depends on if your wireless sensor network can run Matlab code. If not, you can build a turbo code in the C programming language using the code at…
    http://users.ecs.soton.ac.uk/rm/resources/cfixedbcjr/

    Take care, Rob.

  104. Elnaz Says:

    Hi Rob,

    Actually, I have a question on iterative timing recovery and decoding. Since, you helped me alot previously with BCJR decoder, I thought I try to ask this one as well.
    I’m using GD (Gradient Decent algo) to estimate timing points and a Turbo decoder to estimate user bits. My question is that at each iteration when I receive the estimated user bits, how should I use the output of the channel to update the timing estimate?
    Since the channel output is constructed using coded bits, I can’t use the same channel output in my GD, unless, I code the decoded bits of the Turbo decoder before feeding it to GD. Am I correct in assuming this? How does this generally work?

    Thanks a lot,
    Elnaz

  105. Elnaz Says:

    Dear Rob,

    In answer to my last comment, I think, I need to actually change BCJR blocks in my Turbo decoder to make decisions over coded bits as opposed to user bits. I know I should change the sums to sum over different terms in alfa, gamma, betta but I’m not sure how exactly. Could you please guide me how to change your code to get there?

    Thanks,
    Elnaz

  106. Rob Says:

    Hi Elnaz,

    You are quite right - you need the BCJR decoders to generate extrinsic LLRs (or perhaps a posteriori LLRs would suit your application better) for the coded bits. You can do this by creating an additional set of deltas using the same for loops, but with the line…
    deltas2(transition_index, bit_index) = alphas(transitions(transition_index,1),bit_index) + uncoded_gammas(transition_index, bit_index) + betas(transitions(transition_index,2),bit_index);

    Then, you can create an additional set of extrinsic LLRs using the same for loops, with with the line…
    if transitions(transition_index,4)==0

    If you decide that you want the a posteriori LLRs, you can obtain them by adding the extrinsic LLRs to the a priori LLRs.

    Take care, Rob.

  107. Elnaz Says:

    Hi Rob,

    Don’t I need to modify alfas, or betas, or anything else in BCJR?
    Now, I expect that the extrinsic outputs that I get from my Turbo decoder to be equal to parity1 and parity2 (encoded bits) but they’re not.

    Thanks,
    Elnaz

  108. Elnaz Says:

    I’m not sure I understand why replacing encoded_gammas with uncoded_gammas will give me extrinsic LLRs for the coded bits. Could you please explain more.

    Thanks,
    Elnaz

  109. Rob Says:

    Hi Elnaz,

    There is no need to modify the alphas, betas or gammas. In fact, you can see some code that gives extrinsic LLRs for the coded bits at…
    http://users.ecs.soton.ac.uk/rm/resources/matlabexit/

    The reason why replacing encoded_gammas with uncoded_gammas will give you extrinsic LLRs for the coded bits is because extrinsic information is obtained by considering all available information, except for the corresponding a priori information. So, we leave out encoded_gammas when we want encoded extrinsic information, and we leave out uncoded_gammas when we want uncoded extrinsic information.

    Take care, Rob.

  110. Elnaz Says:

    Hi Rob, Am I correct in assuming that sign of encoded extrinsic information (the output of say 1st BCJR decoder) after completing the iterations of Turbo decoder should be equal to parity1 i.e. the coded bits resulted from the first encoder in my 1/3 turbo decoder?
    Currently, I’m not changing the tturbo decoder at all but only replacing the new BCJR blocks. Also, as you advised me before, I am adding systematic output to the extrinsic LLR of the second decoder and feed them as apriori_uncoded_llrs to the first BCJR decoder.
    If all above is right, then whay am I not getting the same parity1 coded bits from the turbo decoder?

    Thanks,
    Elnaz

  111. Rob Says:

    Hmm, I’m not sure. You should still be iteratively exchanging extrinsic LLRs pertaining to the uncoded bits. So you need to output extrinsic LLRs for both the uncoded and encoded bits. You should find that the sign of the LLRs correlates with the encoded bits, as you say. My recommendation would be to compare your code with that which I linked to in my previous reply…

    Take care, Rob.

  112. Elnaz Says:

    Oh, in that case, I was doing wrong. I have basically replaced the old BCJR with new BCJR that outputs extrinsic llrs which is made from delta2. So, turbo decoder was iteratively exchanging new extrinsic llrs.
    But you are saying that turbo decoder should still be exchanging the old outputs (extrinsic llrs for uncoded bits). Here is where I’m not clear. Suppose I get both outputs old and new from each BCJR block, If the turbo decoder should still be exchanging old outputs, then what I should do with the new ones? exchange them too? what does the schematic of the new turbo decoder look like?

    Thanks a lot,
    Elnaz

  113. Rob Says:

    No, you should only exchange the uncoded extrinsic LLRs. You should not use the encoded extrinsic LLRs until the iterative decoding process has finished. After this, you can provide these LLRs to your synchroniser.

    Take care, Rob.

  114. Ideal Says:

    Dear Rob,

    Thanks for your thorough help. You suggest me the code for trajectory plot. I tried the following code. It works for variable and check node curve but doesn’t work for trajectory.

    clear all; clc;
    IA = 0;
    IE = 0;
    results = [IA,IE];
    load newJ.mat; % loading J-function
    Es = 2;
    dv = 3; dc = 6;R=0.5;Ite_max=100;

    snr_L = 10^(Es*0.1);
    sig_Ch = sqrt(8 * R * snr_L);

    % Variable Node curve
    Iav=0:.1:1;
    sigmaA = (interp1(J,SIGMA,Iav));
    sigmaE = sqrt((dv - 1).*sigmaA.^2 + sig_Ch^2);
    Iev=interp1(SIGMA,J,sigmaE);
    Iev(isnan(Iev)) = 1;

    % CNode EXIT curve
    Iac=0:.1:1;
    sigmaCn1 = interp1(J,SIGMA,(1-Iac));
    sigmaEC = sqrt(dc-1) * sigmaCn1;
    Iec = 1 - interp1(SIGMA,J,sigmaEC);
    Iec(isnan(Iec)) = 0;
    plot(Iav,Iev,’b-’,'LineWidth’,1.6),hold on,grid on
    plot(Iec,Iac,’r-’,'LineWidth’,1.6)

    % Trajectory
    while iteration_index == Ite_max
    sig_A = interp1(J,SIGMA,IA);
    IE = interp1(SIGMA,J,sig_A);
    results = [results; [IA,IE]];
    sig_C = interp1(J,SIGMA,IE);
    IA = interp1(SIGMA,J,sig_C);
    results = [results; [IA,IE]];
    end
    plot(results(:,1), results(:,2));

    I am really messed with this program.

  115. Rob Says:

    Hi Ideal,

    It looks to me like your while loop for the trajectory will never be performed. You should replace it with a for loop, such as…
    for iteration_index = 1:100

    Take care, Rob.

  116. Ideal Says:

    Dear Rob,

    I am really very happy. I done that trajectory. Now its quite good. Thanks for your support. Thanks

  117. Ideal Says:

    Dear Rob,

    Thanks for all the responses. One more question please :)

    How can we find the area between the two EXIT curves? I want to find the minimum positive area (distance) when the tunnel open.
    Is there any script for finding the minimum area or distance between the two curves please? Thanks

  118. Rob Says:

    Hi Ideal,

    The code that I have posted at http://users.ecs.soton.ac.uk/rm/resources/matlabexit/ includes a calculation of the area beneath an EXIT curve. If you know the area beneath each EXIT curve, then you can subtract one from the other to find the area within the EXIT tunnel.

    Take care, Rob.

  119. Ideal Says:

    Dear Rob,

    I implemented that method. I was thinking that it will give negative area when the tunnel closes (Area = variable node curve area-check node curve area), but it still gives me the positive area for closed tunnel.

    Can I find the minimum positive distance between the two curves. I thought may it will work but don’t know how to find the minimum positive distance between the two curves? :(
    Thanks

  120. Rob Says:

    Hi Ideal,

    A greater variable node area than check node area does not guarantee an open tunnel. This is the reason why some LDPC codes cannot operate close to the channel capacity. To find the smallest gap between the curves, you’ll have to use interpolation to convert one of the EXIT curves into the domain of the other. You can then subtract each data point in one curve from the corresponding point on the other curve.

    Take care, Rob.

  121. Ideal Says:

    Dear Rob,

    I got some of your idea but not the full one. can you please elaborate a bit more. How can we find the minimum positive distance between the two curve? I really need it. if possible please provide me some example script. Thanks a lot

  122. Rob Says:

    Hi Ideal,

    Here is an example for you…

    IA_outer = 0:0.1:1;
    IE_outer = (0:0.1:1).^2;
    IA_inner = 0:0.1:1;
    IE_inner = 0.5:0.01:0.6;

    IE_outer_new = IA_inner;
    IA_outer_new = interp1(IE_outer, IA_outer, IE_outer_new);
    plot(IA_inner, IE_inner, ‘-’, IE_outer_new, IA_outer_new, ‘–’)

    Take care, Rob.
    IE_inner - IA_outer_new

  123. Ideal Says:

    Dear Rob,

    Thanks for reply,
    I have one simple question. Usually, we implement puncturing in the codeword, for example something like this

    Transmitter side (Uncoded Case)

    temp = randperm(N); randomly permuted vector of size N
    Np = N - N*p; length after puncturing with puncturing fraction p
    pattern = temp(1:Np); Assignment of pattern
    bits = rand(1,N)<0.5; Random binary vector
    % Puncturing
    punc_bits = bits(pattern);
    % Calaculating LLR
    tx = -2*(punc_bits - 0.5); (0->1, 1->-1)
    y = tx + n;
    Lch = 4 * SNR_Linear * y;

    In the receiver side
    llrs = zeros(size(bits));
    llrs(pattern) = Lch;

    My question is what about the coded bits, something like below?
    code_bits = [p data]; (p=parity bits) (codeword)
    tx_bits = -2*(code_bits - 0.5); (0->1, 1->-1)

    % Puncturing
    1. c_punc_bits = tx_bits(pattern); ?

    OR

    2. c_punc_bits = code_bits(pattern);
    tx_bits = -2*(c_punc_bits - 0.5); (0->1, 1->-1)

    Which of the above two way for coded system is right? Thanks
    Please comment

  124. Rob Says:

    Hi Ideal,

    Those two ways are equivalent - you can use either.

    Take care, Rob.

  125. Ideal Says:

    Dear Rob,

    one quick question please. I have defined puncturing fraction p. now i want to distribute it into four different ratios whose overall results should be equal to p.
    i.e. p = p1 + p2 + p3 + p4. how to define four variables based on one variable over a range of values for each variable. Not sure right question:(
    Thanks

  126. Elnaz Says:

    Hi Rob,

    I have another question that is not related to the decoding here.
    I want to implement a convolution of a stream of bits (with zero-padded intervals in between to avoid ISI) with a delayed pulse shape. However, delay is a variable of bit index; I want to implement something like this:

    Sigma over k of (a(k) * g(t-kT-tau(k)),
    where tau(k+1) = tau(k) + noise + some offset;

    Do you know how to implement this?

    Thanks,
    Elnaz

  127. Rob Says:

    Hi Ideal,

    It seems to me that if you want p to be composed of four components, then it should be obtained as their product, not their sum…
    p = p1*p2*p3*p4

    This is because the overall coding rate of serially concatenated codes is given by the product of the individual coding rates.

    Take care, Rob.

  128. Rob Says:

    Hi Elnaz,

    I’m afraid that I’ve never done this before, so I’m not sure how to do it. You may like to look at Matlab’s convolution functions, although I’m not sure that it will let you use a variety of delays…

    Take care, Rob.

  129. nauman Says:

    I am running a simulation of umts turbo codes, with frame length 380, 8 iterations, using max-log-map , but BER results doesn\’t go below 10^-6.
    I am using C code. I want this to go down to 10^-8. any suggestions

  130. Rob Says:

    Hi Nauman,

    If you want your BER results to go down to 10^-6, then you will need to simulate the transmission of at least 10^8 bits. With your frame length, this corresponds to 264k frames…

    Take care, Rob.

  131. nauman Says:

    Hi Rob,

    I have sent these number of bits, I am only concerned about the error floor of
    UMTS turbo codes, and can I achieve 10^-8 BER with the UMTS interleaver.

  132. Rob Says:

    Hi Nauman,

    As you can see in my results above, the error floor of the UMTS turbo code is very steep. It may be that you can’t tell the error floor apart from the turbo cliff…

    Take care, Rob.

  133. Elnaz Says:

    Hi Rob,

    I have one question about adding AWGN:
    I need to plot my error versus (Eb/N0 (dB)) and I have about 4000 bit which after coding with 1/3 rate turbo code, I arrange them into a 111X111 matrix.
    I calculate the noise variance as:

    sigma2 = 1/(2*(10^(EbN0/10)));

    r = R + sqrt(sigma2).*randn(size(R,1),size(R,2));

    But I’m having second thoughts as if I have to somehow enter the message length 4000X3 bits or 4000 bits into the above equations. Should I?

    Thanks,
    Elnaz

  134. Rob Says:

    Hi Elnaz,

    You should be adding the noise to the 12000 encoded bits. One thing to consider is that you are using purely real valued noise here. If you are using BPSK then this is okay. But otherwise, you should be using complex valued noise…

    r = R + sqrt(sigma2)*(randn(size(R))+i*randn(size(R)));

    Take care, Rob.

  135. Elnaz Says:

    Hi Rob,

    Yes, I am adding the noise to all the samples. The problem is with power of noise that I\’m adding. I\’m using a 1/3-rate turbo code and then I multiply my coded bits each with a 2D sinc function and then adding the noise.
    Does the above formula: sigma2 = 1/(2*(10^(EbN0/10))) still hold here?

    Thanks,
    Elnaz

  136. Rob Says:

    Hi Elnaz,

    Your equation sigma2 = 1/(2*(10^(EbN0/10))) can be rearranged to give N0 = 2*sigma^2. This implies that your noise will have two dimensions (i.e. it will be complex). If you were using purely real-valued noise, then N0 = sigma^2.

    Take care, Rob.

  137. Elnaz Says:

    Shouldn’t I use something in line with: Eb/N0 = Fs/(2 x R x sigma2) ?

    where

    R = code rate 1/3 in my case
    Fs = No. of samples per modulated symbol. Since my my system is two-dimensional, I guess I will have to take the no. of samples in my sinc(x).sinc(y) function.

    Since I’m adding pure real-valued noise then: Eb/N0 = Fs/(R x sigma2) .

    Actually, I think my error vs. EbN0 plot are shifted to the right compared to the correct plots as if I’m not adding enough noise power. That’s the reason I’m trying to increase the noise power somehow.

    Thanks,
    Elnaz

  138. Rob Says:

    Hi Elnaz,

    When I perform a baseband simulation, I use SNR = Es/N0, where Es is the energy per symbol. I then convert to Eb/N0 by using Es = R*log2(M)*Eb, giving Eb/N0 = Es/(N0*R*log2(M)). Here M is the number of constellation points in the modulation scheme.

    Take care, Rob.

  139. Elnaz Says:

    Hi Rob,

    Yes, right. I depends, I think, where we’re adding the noise in the system. What I’m doing is somewhat different than a standard modulation and that is the reason I have difficulties applying the same Eb/N0 concept to my problem.

    Actually, I am rearranging my stream of coded bits into a matrix and then convolve this matrix with a 2D sinc function ending up with an image (2D waveform). Therefore, I have an image wherein the coded bits are hidden. I add my noise to this matrix.
    I want to know how exactly I should calculate the noise variance in terms of Eb/N0.
    Any reference or suggestion would be great.

    Thanks,
    Elnaz

  140. Rob Says:

    Hi Elnaz,

    I’m afraid that I haven’t come across the approach you are describing here so I’m afraid that I can’t help you with the relationship between Eb/N0 and the noise variance. My suspicion is that N0 = 2sigma^2, since you are probably using complex noise. The bit I’m not sure about is the value of Eb, or Es…

    Take care, Rob.

  141. Ideal Says:

    Dear Rob,

    In your post above (May 25th, 2012 at 11:31 am), you suggest me interpolation to convert one of the EXIT curves into the domain of the other. In this way we can then subtract each data point in one curve from the corresponding point on the other curve. This way can find the smallest gap between the curves.

    I already implement this method and it is working fine but now I want to write these step of interpolation of two curves in a mathematical way but feeling difficulty. Please can you give me example of writing this? :(

  142. Rob Says:

    Hi Ideal,

    Suppose you have two data points (x1,y1) and (x2,y2). You wish to find the y-coordinate y3 that corresponds to a particular x-coordinate x3. You can interpolate along a line passing through the two known data points using the following steps…

    m = (y2-y1)/(x2-x1)
    c = y1 - m*x1
    y3 = m*x3+c

    Take care, Rob.

  143. somya Says:

    the exit chart graph is plotted in between Eb/No vs BER.i got the out put as after10 trial and 500 message bit passed i got the waveform.can i calculate the code rate?

  144. Rob Says:

    Hi Somya,

    The code rate of a UMTS turbo code is given by N/(3*N+12), where N is the interleaver length. In the case of UMTS, the interleaver length N should in the range 40 to 5114 bits.

    Take care, Rob.

  145. Stas Says:

    Hello Rob,
    I know you very competent in turbo codes and MIMO systems. I read some papers from L.Hanzo and you.
    I work on turbo-MIMO matlab code: spatial multiplexing MIMO with MAP (or ZF, MMSE) and turbo-code (PCCC with MAP).
    Could you please to suggest me any help in this field?

  146. Rob Says:

    Hello Stas,

    I’m afraid that I don’t have any Matlab code for spatial multiplexing MIMO, but the Matlab code that I have provided on this page can help you with your turbo-code - it is a PCCC with MAP.

    Take care, Rob.

  147. Ideal Says:

    Dear Rob,

    Thanks for your help. Please one more question.

    Do you have any script for plotting “zoom out a portion of plot within the same plot”? :(
    Thanks

  148. Rob Says:

    Hi Ideal,

    I’m afraid that I don’t, because I do all my final-version plotting in Gnuplot, rather than Matlab. I’m sure you will be able to find some code for this on Google though.

    Take care, Rob.

  149. Ideal Says:

    Dear Rob,

    Yes I did that plot very well thanks

  150. Ideal Says:

    Dear Rob,

    You explain me last time the way of puncturing in MATLAB. I did that one and working very good. It was the way for binary channels.

    But Now I am think if I am using QPSK or 4-PAM, in this case, each symbol consist of two bits. I am thinking to apply puncturing (pairwise bits), i.e., puncturing symbol treating all the bits uniformly but I don’t know how to implement pairwise puncturing. Please can you give me any idea, how to implement it. Thanks

  151. Rob Says:

    Hi Ideal,

    My feeling is that puncturing bits in pairs places an unnecessary constraint on your design and that it may degrade your performance. My recommendation would be to puncture the bits in the way you have already been doing it, then pair the remaining bits up and modulate them.

    Take care, Rob.

  152. Ideal Says:

    Dear Rob,

    Thanks for your advise. But after puncturing, I need to calculate the LLR for each bit, i.e., after puncturing I need to perform QPSK modulation and then calculate the LLR(x1) and LLR(x2) in a symbol and then calculate the EXIT chart? I think your idea is very useful but..

    I am still confuse please can you explain bit more. Thanks

  153. Rob Says:

    Hi Ideal,

    You just need get the LLRs from the demodulator, then insert a zero-valued LLR to replace each punctured bit. You should think of the puncturer as being independent from the modulator.

    Take care, Rob.

  154. Ideal Says:

    Dear Rob,

    I am thinking of first puncturing the codebits and then modulate them into QPSK and then transmit. On the receiver side, I will receive y=x + n, x is the QPSK symbol and n is the noise. Now LLR(y) = 2/sigma *y is the right thing? or I need to calculate the LLR for real bits and then for imaginary bits and combine the LLR into one LLR.

    Then I can add the same pattern of punctured, I did on the transmitter side.

    Am I right or any sample example will be very helpful please. I want to calculate the EXIT chart of the LDPC code. Thanks

  155. Rob Says:

    Hi Ideal,

    If you use Gray coded QPSK then you can use…
    LLR1 = sqrt(2)*real(y)/sigma^2;
    LLR2 = sqrt(2)*imag(y)/sigma^2;

    I think…

    Take care, Rob.

  156. Ideal Says:

    Dear Rob,

    Thanks but I am still confuse. Like I punctured some codebits, then I modulate using the Gray mapping QPSK, now each bit is converted into a symbol (two bits), Then similarly I calculate the bitwise LLR for real bit 1 and imaginary bit 2. It means that I have two LLRs on the receiver side, LLR1 and LLR2. How can I combine two LLRs into one LLR so that I can assign zeros to the punctured position(I did at the transmitter).

    I am still not understanding the cooprations between bits and symbols? After all to calculate the extrinsic mutual information, I need one LLR vector (either bit 1 or bit 2 or combined) that is the question? Thanks for your help please

  157. Rob Says:

    Hi Ideal,

    There is no need for you to “combine two LLRs into one LLR”. Suppose you have 100 bits, then you puncture 40 of them to leave 60 bits. After that you combine two bits per QPSK symbol, to give 30 symbols in total. In the receiver, you can use the code I provided above to separate each QPSK symbol in to two LLRs. So you go from 30 symbols to 60 LLRs. After that you can insert 40 zero-valued LLRs to get you back to 100 LLRs.

    Take care, Rob.

  158. Ideal Says:

    Dear Rob,

    I am really very thankful to you for your detailed example. So it means that LLR1 is of 30 bits and LLR2 is of 30 bits too and total of 60 bits so LLR = [LLR1, LLR2]; to have LLR equal to 60 bits.

    Secondly I need to use QPSK gray mapping to convert from 60 bits to 30 symbols. Can I use your script for QPSK gray mapping scheme, you provided for QPSK demapper exit chart?

    I am very much thankful to you.

  159. Rob Says:

    Hi Ideal,

    That’s right. You can use the QPSK code I have put on my website for this job.

    Take care, Rob.

  160. Ideal Says:

    Dear Rob,

    Thanks, I implement all the steps and now my algorithm is working. But I have one question about the LLR, You wrote that

    If I use Gray coded QPSK then I can use…
    LLR1 = sqrt(2) * real(y) / sigma^2;

    My question is why you write sqrt(2), I was thinking, it will be just 2 without square root, i.e..
    LLR1 = 2 * real(y) / sigma^2;

    Please can you clarify me or any reference will be Fine as well. Thanks

  161. Rob Says:

    Hi Ideal,

    This is because QPSK puts half of its power into the I signal and the other half into the Q signal. By contrast, BPSK puts all of its power into the I signal. This is why different coefficients are needed.

    Take care, Rob.

  162. Elnaz Says:

    Hi Rob,

    As you know, I am using a Turbo Decoder which includes your BCJR algo in my application. However, I am getting an inferior result which is traced down to my Turbo Decoder. I have a number of uncertainties which may be the culprit.
    First is the format you defined the Trellis structure in your BCJR code. I have translated my Trellis (i.e. poly2trellis(3,[7 5],7); in MATLAB) aacording to your structure. But, I feel, I can never be 100% sure unless check it with you. So, could you please have a look at this and conform its correctness:

    % FromState, ToState, UncodedBit, EncodedBit
    transitions = [1, 1, 0, 0;
    2, 3, 0, 0;
    3, 4, 0, 1;
    4, 2, 0, 1;
    1, 3, 1, 1;
    2, 1, 1, 1;
    3, 2, 1, 0;
    4, 4, 1, 0];

  163. Rob Says:

    Hi Elnaz,

    Actually, there is a simple way to know if you have programmed the turbo code correctly or not. You should start by drawing the turbo code EXIT chart by using the histogram method. After that, you should do it again, but using the averaging method. If there are no problems with your code, you will get the same result with both methods. If there are problems, the two EXIT charts will look very different to each other.

    Take care, Rob.

  164. Elnaz Says:

    Ok; meanwhile, I’m also suspicious if using convenc which doesn’t force termination may be the culprit also. So, I need to add zeros to the end of the input bits before convenc, I guess. The question is how many zeros for poly2trellis(3,[7 5],7) to ensure termination?

    Thanks,
    Elnaz

  165. Elnaz Says:

    Hi Rob,

    I need to correct my previous comment by changing the question to: What bits should I add to my input stream to ensure encoder termination? Is there any way to find out other than manually drawing the trellis?

    Thanks,
    Elnaz

  166. Rob Says:

    Hi Elnaz,

    Since your encoder includes two memory elements, you will need two extra bits to terminate it. These bits should be set equal to the feedback bits. If you take a look at the UMTS encoder schematic, you will see what I mean…

    Take care, Rob.

  167. Elnaz Says:

    Hi Rob,

    Do you think that not using termination can contribute to noticable error when 4000 message bits are encoded with a 1/3-rate Turbo code?

    Elnaz

  168. Ideal Says:

    Hi Rob,

    Thanks for your comments. I have worked out the things and well with gray mapped QPSK. Now please can you tell me a bit about the anti-gray mapped QPSK.

    I mean, how to mapp from bits to symbols (ant-gray QPSK) and what will be the LLR expressions. Thanks a lot for your thorough help.

  169. Elnaz Says:

    Hi Rob,

    I studied the parts in the report which deals with termination and also the way you have implemented it.
    Actually, since my application is different than yours, I can not exactly do what you did. I am using a 1/3 rate turbo encoder. Therefore, I will be having two tail bits padded to the systematic output, and the parity 1 and parity 2 will each also be two bits longer than the original stream. These 3 stream of bits then pass through a channel. The discrepancy between my application and your application is that in the receiver site , I won’t have access to the termination bits of the second encoder to feed the second BCJR. But for the 1st BCJR there is no problem since termination bits of the 1st encoder is already padded to the systematic output and passed through the channel. So, I will have the channeled version of the termination bits of the 1st encoder but not the second one.
    What would you suggest?

    Thanks,
    Elnaz

  170. Rob Says:

    Hi Elnaz,

    Getting the termination wrong can give you a few bit errors per frame. So this would give you an error floor at about 10^-3, using a frame length of 4000 bits.

    The UMTS turbo code solves the problem you’ve described by transmitting the bits that are padded onto the interleaved bit sequence in order to terminate the second encoder. The alternative is to pad the apriori LLRs with two zero-valued LLRs.

    Take care, Rob.

  171. Rob Says:

    Hi Ideal,

    If you use anti-Gray mapping (also known as natural mapping) then you can’t use the simple demodulator equations any more. You can see how to implement this using the code that I provided at…
    http://users.ecs.soton.ac.uk/rm/resources/matlabexit/#comment-1545

    Take care, Rob.

  172. Elnaz Says:

    Hi Rob,

    I implemented the alternative i.e. padding the apriori LLRs with two zeros. And my apriori encoded LLRs already include two encoded and channeled termination bits (output of component_encoder are passed through channel).
    I am using the encoded outputs of BCJR decoder at each iteration.
    Is it correct to use their entire length or the last two bits are erroneous?

    Thanks,
    Elnaz

  173. Rob Says:

    Hi Elnaz,

    All of the LLRs should be good to use. The last tow will pertain to the two termination bits.

    Take care, Rob.

  174. Ideal Says:

    Dear Rob,

    Thanks for QPSK demapper exit chart code. Can you advise me a bit its implementation for the LDPC EXIT chart, i.e., I want to simulation for Variable node and check node (3,6) half rate. In that case, we will have two a-priori LLRs from check nodes and one channel LLR in order to calculate the variable node extrinsic information. Can you advise me about its implementation like this. please

  175. Rob Says:

    Hi Ideal,

    As you say, each variable node takes LLRs from it’s connected check nodes and one LLR from the QPSK demodulator. If you use natural QPSK mapping, there is a benefit to iterating between the demodulator and variable nodes, in addition to between the check and variable nodes. In which case, each variable node can generate one extrinsic LLR to give to the demodulator.

    Take care, Rob.

  176. Elnaz Says:

    Hi Rob,

    I don\’t see any performance gain after adding termination. I changed BCJR decoder line from
    betas(:,length(apriori_uncoded_llrs))=0;
    back to ….
    betas(1,length(apriori_uncoded_llrs))=0;
    And, I pad two zeros to apriori uncoded LLRs before feeding them to the decoders.
    Also, previously I changed your BCJR code to also output encoded LLRs and I am only using those.
    Is there anything I might be missing?

    Thanks,
    Elnaz

  177. Elnaz Says:

    Dear Rob,

    I want to know, is there a way to test turbo decoder performance independant of modulation and channel scheme?
    My observation is that in my application the turbo decoder performs inferior than what is expected. The EXIT charts that you advised me to draw, I think, test the encoding, modulation, and one decoder but not the turbo decoder.
    What would you suggest?

    Many thanks,
    Elnaz

  178. Ideal Says:

    Dear Rob,

    Thanks for reply,

    I think still I can’t understand the operation of iterations between the demodulator and variable node, and also between the variable node and check node. May be I don’t still have a clear overview of these iterations. Any clarification, how these iterations will work in simulation setup will be appreciated please.

  179. Rob Says:

    Hi Ideal,

    You can see what I mean in Figure 2 of this paper…
    http://gps-tsc.upc.es/comm2/publications/C_2006_ISTC06_Lahuerta_1274.pdf

    Here you can see that LLRs are flowing from demodulator to variable node, but also from variable node to demodulator.

    Take care, Rob.

  180. Rob Says:

    Hi Elnaz,

    Termination doesn’t make any significant difference to the performance in the turbo cliff region of the BER plot. It only really makes a difference in the error floor region. Probably your error floor is at such a low BER that you can’t see it (and its improvement) in your BER plots.

    You can test that the turbo decoder is operating property by plotting decoding trajectories into the EXIT chart. If there is not a good match between the trajectories and the EXIT functions, then you know something is going wrong.

    Take care, Rob.

  181. Elnaz Says:

    Hi Rob,

    I plotted the EXIT charts and the two are different. The one with histogram method is more square-like but the other is more elliptical.
    I know this means there is something wrong but I don’t know how should I further debug the problem.
    All I did is that I replaced your encoding and modulation with mine. I don’t have demodulator and my frame-length is about 4000 bits and I used termination but Eb/N0 value was -4 same as yours.
    Can you help me find out what is wrong here? I don’t exactly understand what these charts are measuring.

    Thanks,
    Elnaz

  182. Rob Says:

    Hi Elnaz,

    The first thing I would do is try to narrow down the problem to either the turbo code or to the demodulator. You can do this by seeing how the mutual information of the LLRs provided by the demodulator vary with SNR. You can plot this using both the averaging and histogram methods. If your demodulator is working, then these plots will match each other, suggesting that the problem is in the turbo code. If the plots don’t match then it suggests that the problem is in your demodulator.

    Take care, Rob.

  183. Elnaz Says:

    Hi Rob,

    But I do not have demodulator only modulator. Did you mean modulator?
    Without demodulator should I still expect to get similar plots (histogram and averaging) with different SNRs?
    By the way, I ran your code to see what should I expect with my code. I’m not even sure if those plots I’m getting are correct. They are not exactly matching either. Is there any way I can send you the figures from your code?

    Thank you so much,
    Elnaz

  184. Rob Says:

    Hi Elnaz,

    You must have some kind of demodulator - this is the part of your code that converts the received signal into LLRs. The histogram and averaging methods will never give identical results, but the results should be close to each other. You may like to compare the results you get from running my code with the results that I’ve provided at the top of this page. Can you provide a link to a .jpg of your results?

    Take care, Rob.

  185. Elnaz Says:

    Rob, thank you so much for your help.
    I see that by increasing SNR in your code, the discrepancy between histogram and averaging charts as well as EXIT functions in each graph decreases.

    This is the graph I get from running my code with averaging method:
    http://www.sendspace.com/file/epsckt

    And, this is the one with histogram method:
    http://www.sendspace.com/file/69eon8
    (please use the download link at the bottom of the page)

    Elnaz

  186. Rob Says:

    Hi Elnaz,

    These EXIT functions are significantly different and so I suspect that there is a bug somewhere in your code. This could be in your turbo encoder, modulator, demodulator or turbo decoder. You should try to narrow it down…

    Take care, Rob.

  187. Elnaz Says:

    Dear Rob,

    I just want to make sure I understand correctly. When you say “If your demodulator is working, then these plots will match each other, suggesting that the problem is in the turbo code” do you mean that e.g. the histogram graphs of different SNR values should match each other? Or that for each SNR value the histogram graph should match the averaging graph?
    What I see with running your code is that by changing SNR value graphs significantly change as well but by increasing the SNR the similarity between histogram and averaging graphs grows too.
    Am I correct?

    Elnaz

  188. Ideal Says:

    Dear Rob,

    can you please extend your MATLAB code for EXIT demapper (natural QPSK mapping) to half rate regular LDPC EXIT chart (natural QPSK mapping). Please I really need it. Please help me in this regards. I will be thankful to you.

  189. Rob Says:

    Hi Elnaz,

    I mean that for each SNR value, the histogram graph should match the averaging graph.

    Take care, Rob.

  190. Rob Says:

    Hi Ideal,

    I’m afraid that I don’t have any Matlab code that combines LDPC with QPSK. The QPSK demodulator has an input and an output pertaining to the LDPC-encoded bits - in main_exit.m from QPSKEXIT.zip, the input is called a_a and the output is called a_e. Likewise, the variable node decoder has an input and an output pertaining to the LDPC-encoded bits - in main_exit_vnd.m the input is called c_a and the output is called c_e. It’s just a matter of connecting these inputs to these outputs - you should also use an interleaver and deinterleaver though.

    Take care, Rob.

  191. Elnaz Says:

    Hi Rob,

    I have some results. At higher SNR values e.g. SNR=2, my graphs almost match. Those graphs that you saw earlier were from SNR=-4.
    Then, according to your advice above, this means that there is something wrong with the decoder. However, I replaced my encoder and decoder which are your codes exactly only with different transition matrix, and yet I get almost same graphs as of when using my encoder and decoder!
    At this point, I guess, I’m left without a clue as to what is wrong with my turbo decoding.
    What would you suggest?

    Thanks,
    Elnaz

  192. Ideal Says:

    dear Rob,

    thanks for the suggestion. I will try it to combine the ldpc with qpsk. but how can I add interleaver and deinterleaver? is there any matlab command or function which perform interleaving deinterleaving. thanks for your support

  193. Ideal Says:

    Dear Rob

    I find the QPSK Exit script written by you but I cannot find the main_exit_vnd.m file in you resources. please can you update for me thanks

  194. Rob Says:

    Hi Elnaz,

    I’m afraid that you will need to track down the bug in your code and fix it. I would suggest starting from my code and gradually converting it into your code, checking that the averaging and histogram methods give the same result after each stage of the conversion. In particular, you may like to double check that your trellis and component encoder correspond to each other. Something you may like to do is rewrite the encoder so that it is trellis-based, rather than shift-register based. This way, you can copy-and-paste the transitions from the decoder to the encoder, allowing you to be sure that they match…

    Take care, Rob.

  195. Rob Says:

    Hi Ideal,

    An interleaver and a deinterleaver can be implemented in Matlab as follows…

    interleaver = randperm(length(bits));
    interleaved_bits = bits(interleaver);
    deinterleaved_bits(interleaver) = interleaved_bits;

    You can find main_exit_vnd.m at…
    http://users.ecs.soton.ac.uk/rm/wp-content/LDPC.zip

    Take care, Rob.

  196. Elnaz Says:

    Hi Rob,

    I’m not clear on one point as to why you think there is a bug in the encoder/decoder part of my code? since when I replaced my encoder and decoder with your “component_decoder” and “component_encoder” codes I still get almost the same graphs at SNR=-4.
    Having this am I correct in assuming that it is the modulation/demodulation part rather than the coding/decoding part?

    Elnaz

  197. Rob Says:

    Hi Elnaz,

    You are right - this suggests that the problem is in the modulator or demodulator.

    Take care, Rob.

  198. Elnaz Says:

    Hi Rob,

    Thanks; Therefore, my takeaway point would be, correct me if I’m wrong, that depending on the modulation/demodulation used Histogram and averaging graphs can look different on low SNRs (depending on modulation).
    Since what I do before turbo decoding (I call it modulation) is not a standard modulation technique but the model of some sort of channel, I guess it is burdening the decoding part and cause this diiference at low SNR.
    Here is my BER plot. Could you please take a look at it and let me know what you think?

    http://www.sendspace.com/file/d7brlw

    Thanks,
    Elnaz

  199. Rob Says:

    Hi Elnaz,

    Your BER is heading towards zero as the SNR increases, so your system is as least partially working. In my experience, the averaging and histogram methods should agree with each other, even at low SNRs. It sounds to me like your method for converting the received signal into LLRs is not quite right. You may like to use my display_llr_histograms.m Matlab code for checking this. You can see lots of discussion about this in the comments of…
    http://users.ecs.soton.ac.uk/rm/resources/matlabexit/

    Take care, Rob.

  200. Ideal Says:

    Hi Rob,

    I am trying to combine the QPSK (natural) demaper exit with with LDPC exit but still cannot get the clue. Please help me in this regards a bit more. Thanks for all your help

  201. Ideal Says:

    Dear Rob,

    Now I understand the concept of QPSK demapper plus ldpc exit chart but still confusion in implementing it it matlab. I have initiallt two questions.

    1. I am not understanding the iterations between demapper + variable node decoder + check node decoder.

    2. Do I need to implement the soft demodulation bitwise (symbol-wise) or at first I calculate the channel LLR a vector and then apply demapping. and again don’t know how to implement iterations?

    Please help me in this regards. Thanks a lot

  202. Rob Says:

    Hi Ideal,

    You can see an example of implementing iterations in main_ber.m, which you can download from this page. When you perform demodulation, you will need a for loop that demodulates each symbol individually.

    Take care, Rob.

  203. Ideal Says:

    Dear Rob,

    I did some kind of flow for the transmitter and reciever for first iteration.
    Transmitter:
    codebits –> interleaver –> group/mapping(QPSK) –> adding noise and txt.
    Receiver:
    Demapper input: a_a(zeros at first iteration) + received symbols
    ouputs: a_e and then perform the deinterleaving
    variable node decoder inputs: a_e + a_a(from check node)
    outputs: c_e and then perform interleaving
    now 2nd iteration start at the input of demapper with a_a = c_e(interleaved) with channel signal.

    But I am thinking to introduce the soft values at the input of the demapper as was done by ten Brinks or the above procedure is OK? Thanks

    and I think I need to have for loop for the above process.. Thanks

  204. Rob Says:

    Hi Ideal,

    Your flow looks good to me. I’m not sure what you mean when you say “I am thinking to introduce the soft values at the input of the demapper”. It seems to me that you are already doing this when you say “2nd iteration start at the input of demapper with a_a = c_e(interleaved) “.

    As you say, you can use a for loop to perform the iteration. One thing to think about is what decoder activation order you will use within each iteration of your loop. Examples of potential activation orders include:
    1) demodulator - variable node - check node
    2) demodulator - variable node - check node - variable node
    3) demodulator - variable node - demodulator - variable node - check node
    4) demodulator - variable node - check node - variable node - check node
    and so on…

    I would recommend option 1, since it activates each of the decoders equally often…

    Take care, Rob.

  205. Elnaz Says:

    Hi Rob,

    Are you familiar with Cramer-Rao bound analysis?

    Thanks,
    Elnaz

  206. Ideal Says:

    Dear Rob,

    Thanks for all your fruitfull suggestions. I appreciated it. I am really interested in calculating the EXIT function of the variable node decoder(VND). I did implement it (QPSK gray and natural mapping) and hopefully the results are good.

    I just did the iterations between the demapper and the variable node decoder as,

    ist iteration on transmitter side:

    demapper input (chanel plus a priori LLR, (L_ma) (all zeros)) = L_me (out)
    VND input (a priori LLR from check node plus L_da(L_me(Interleaved))) = L_de (out)

    2nd iteration

    demapper input= same channel + L_ma, where L_ma = L_de(de-interleaved) and same out L_me

    VND input (a priori LLR from check node plus L_da(L_me(Interleaved))) = L_de

    and so on.

    EXIT chart

    I can calculate the VND EXIT curve using L_de and the demapper curve using L_me.

    Now one question:

    I want to implement puncturing in this setup. please can you give me feedback about the puncturing implementation please. Thanks again

  207. Rob Says:

    Hi Elnaz,

    I’m afraid that I have never used the Cramer-Rao bound…

    Take care, Rob.

  208. Rob Says:

    Hi Ideal,

    The simplest way to implement puncturing is to do it at the same time as interleaving.

    You can design the interleaver/puncturer using…
    interleaver = randperm(number_of_ldpc_encoded_bits);
    interleaver_puncturer = interleaver(1:number_of_bits_after_puncturing);

    You can perform puncturing in the transmitter using…
    interleaved_punctured_bits = ldpc_encoded_bits(interleaver_puncturer);

    You can perform puncturing in the receiver using…
    apriori_interleaved_punctured_llrs = extrinsic_ldpc_encoded_llrs(interleaver_puncturer);

    You can perform depuncturing in the receiver using…
    apriori_ldpc_encoded_llrs = zeros(1,number_of_ldpc_encoded_bits);
    apriori_ldpc_encoded_llrs(interelaver_puncturer) = extrinsic_interleaved_punctured_llrs;

    Take care, Rob.

  209. Ideal Says:

    Dear Rob,

    I am really thankful for your responses. One question about the soft demodulation.

    In your script of soft_demodulate.m, you are converting from symbol to bit extrinsic llr (a_e). Now my question is that do we need to take into account the two variable node as well, i.e., one symbol consist of two bits (x1×0), so for each bit one variable node of ldpc code, it means for one symbol, we need to use two variable nodes connecting with check nodes. I am confused here?

    2ndly, If I want to plot the EXIT curve between the check node and demapper, I think, do I need to calculate the demapper curve after performing the complete iterations and using the llr (a_e) value from last iteration( using in you average MI script) so that the demapper EXIT curve shows some slop. Can you tell me the right way please. Thanks again

  210. Rob Says:

    Hi Ideal,

    There is no need to modify the soft demodulator to take the variable nodes into account. Taking care of the variable nodes is the job of the variable node decoder.

    There are a few ways of plotting the EXIT charts of your 3-stage concatenated scheme. The way that I would recommend is to treat the LDPC decoder as a black box that the demodulator exchanges LLRs with. You can then draw a single EXIT function for this black box. You can achieve this by using the following process for each value of Ia in the set 0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0:

    1) Generate some random bits
    2) Encode these bits using the LDPC encoder, in order to generate the encoded bits
    3) Use these encoded bits as the input to generate_random_llrs, together with the current value of Ia
    4) Give the resultant LLRs to the LDPC decoder and perform 10 decoding iterations between the variable node and check node decoders, then obtain the extrinsic LLRs out of the variable nodes
    5) Measure the mutual information Ie of these extrinsic LLRs

    You can then plot Ie vs Ie.

    Take care, Rob.

  211. Ideal Says:

    Dear Rob,

    Thanks for the simple example.

    One thing please. I want to use your modulate.m and soft_demodulate.m script for the 4-PAM constellation, where 4-PAM symbol ={0,1/3,2/3,1} and the symbol energy I calculate E_s = 1/M(0+1/3+2/3+1)d=1/2d (optical),
    can I use your scripts by just changing the constellation labels and bit labels and what should I need to multiply with symbols for normalization, i.e.,
    constellation_points = [0; 1/3; 2/3; 1]/(which factor rather than sqrt(2)).

    Thanks

  212. Rob Says:

    Hi Ideal,

    Yes - it is as simple as changing the constellation points and bit labels. You should normalise by using…

    constellation_points = constellation_points/sqrt(mean(abs(constellation_points).^2))

    Take care, Rob.

  213. Ushi Says:

    Hi Rob,

    Your code is very helpful. I need to generate LLR values of the coded bits at the decoder. I tried your code and it didn\’t work.

    % Calculate encoded extrinsic transition log-confidences. This is similar to
    % Equation 2.18 in Liang Li’s nine month report or Equation 4 in the BCJR paper.
    deltas2=zeros(size(transitions,1),length(apriori_encoded_llrs));
    for bit_index = 1:length(apriori_encoded_llrs)
    for transition_index = 1:size(transitions,1)
    deltas2(transition_index, bit_index) = alphas(transitions(transition_index,1),bit_index) + uncoded_gammas(transition_index, bit_index) + betas(transitions(transition_index,2),bit_index);
    end
    end
    % Calculate the encoded extrinsic LLRs. This is similar to Equation 2.19 in
    % Liang Li’s nine month report.
    extrinsic_encoded_llrs = zeros(1,length(apriori_encoded_llrs));
    for bit_index = 1:length(apriori_encoded_llrs)
    prob0=-inf;
    prob1=-inf;
    for transition_index = 1:size(transitions,1)
    if transitions(transition_index,4)==0
    prob0 = jac(prob0, deltas2(transition_index,bit_index));
    else
    prob1 = jac(prob1, deltas2(transition_index,bit_index));
    end
    end
    extrinsic_encoded_llrs(bit_index) = prob0-prob1;
    end

    Does it computes the LLRs of (lc+ld+le+lf) ? I need just lc.

    Thanks,
    Ushi

  214. Ideal Says:

    Dear Rob,

    Thanks for the response.

    You also suggest me some iterative loop for QPSK but I am thinking, if I just generate the random LLRs and give them to the variable node input and then take out the extrinsic LLRs from the variable node and measure the MI of this extrinsic LLR. In this situation, I didn’t see any iterations between the demapper and the variable node. Thats why I was doing the following steps for 3,6 half rate code so dv=3.

    Receiver side:
    first iteration demapper:
    1)Lm_e=perform soft demodulation with all zeros a priori LLRs (from VND).
    2) Ld_e=input the Lm_e to the VND plus all zeros priori LLRs(incoming from CND (dv-1)).

    2nd iteration demapper:
    1)Lm_e=perform soft demodulation with a priori LLRs (ld_e from VND).
    2) Ld_e=input the Lm_e to the VND plus a priori LLRs(from CND, this time not all zeros (random)).

    this iterative process carry on until the iteration count end or MI from the demapper stops improving.

    After that I got the final Ld_e from the above iterative process and I use that to measure the VND extrinsic MI for each point of the IAs and this is called VND EXIT chart?

  215. Rob Says:

    Hello Ushi,

    The code you have provided will calculate extrinsic LLRs that pertain to the output bits of the corresponding component encoder. Using the notation from my main_ber.m file, these LLRs would be c_e for the first component decoder and d_e for the second component decoder.

    Take care, Rob.

  216. Rob Says:

    Hi Ideal,

    You are close getting it right, but your variable node has d_v+1 number of ports - one connected to the demapper and d_v connected to the check nodes. Therefore you should be generating d_v number of random apriori LLRs and you should be measuring the mutual information of d_v number of extrinsic LLRs. You currently have d_v-1 number of LLRs in both cases.

    The LLR that is output on a particular one of the variable nodes ports should be equal to the sum of the LLRs that are input at the other d_v ports. So,
    1) the LLR that is passed to the demapper by the variable node should be equal to the sum of the d_v number of randomly generated LLRs.
    2) the LLR that the variable node outputs on a particular one of its check-node-connected ports should be equal to the LLR provided by the demapper and the d_v-1 randomly generated LLRs that are provided on the other check-node-connected ports.

    Take care, Rob.

  217. Ideal Says:

    Dear Rob,

    Thanks, this is right now. One thing about the soft demodulation. I am wondering that you are using the same equation (2) in ten brinks paper “Iterative demapping for QPSK modulation” Electronic letters July 1998?

    I think that equation (2) is calculating bitwise LLR value. If the soft_demodulate.m is the output of same equation then I am wondering where is the first additive term. If not then what is the possibility of using that equation. I mean how can we implement that equation? :) Thanks for discussion

  218. Ideal Says:

    Dear Rob,

    One more thing in plotting the trajectory of QPSK. I am using the following code. It works well in Gray mapping but not for natural mapping.
    IA = 0;
    IE = 0;
    results = [IA,IE];
    snr_L = 10^(SNR*0.1);
    sig_Ch = sqrt(8 * 0.5 * snr_L);
    % Trajectory (dv=3,dc=6)
    for iteration_index = 1 : 100
    sig_A = (interp1(J,SIGMA,IA));
    sig_D = sqrt(sig_Ch^2 + 3*(sig_A.^2)); % one channel + 3 apriori
    sig_E = sqrt((3 - 1).*sig_A.^2 + sig_D.^2); % VND extrinsic
    IE = interp1(SIGMA,J,sig_E);
    results = [results; [IA,IE]];
    sig_C = interp1(J,SIGMA,(1-IE));
    sig_C(sig_C>20) = 20; sig_C(sig_C20) = 20; sig_EC(sig_EC<=0) = 0;
    IA = 1 - interp1(SIGMA,J,sig_EC);
    results = [results; [IA,IE]];
    end
    plot(results(:,1), results(:,2),’g-.’); hold on

  219. Rob Says:

    Hi Ideal,

    Equation (2) in the paper you mention calculates the aposteriori LLR. By contrast, my soft demodulator calculates the extrinsic LLR, which is equal to the aposteriori LLR minus the apriori LLR. The first additive term is the apriori LLR. Therefore, my soft demodulator is equivalent to the right hand term in equation (2) of that paper.

    It looks to me that your trajectory code is using ten Brink’s equations for the VND and CND EXIT functions. These hold for Gray mapping, but not for natural mapping, as you have found. When using natural mapping, you will need to use your simulation to get the VND EXIT function, rather than an equation.

    Take care, Rob.

  220. Ideal Says:

    Dear Rob,

    It means in order to calculate the EXIT chart, we can use the extrinsic LLR rather than the aposteriori LLR. So we can just implement the equation (2) without the a prioi LLR and fed that extrinsic LLR into the LDPC decoder after interleaving?

    Or we still need the aposteriori LLR to fed to the LDPC decoder? If that is the case then how can we introduced the a priori LLR in simulations? Thanks

  221. Rob Says:

    Hi Ideal,

    Yes, it is the extrinsic LLRs that should be iteratively exchanged with the variable node decoder. The aposteriori LLRs should only be used once the iterative decoding process has finished, in order to provide the final output. If the aposteriori LLRs are used during the iterative decoding process, then this will become a positive-feedback loop and the performance will be severely degraded.

    Take care, Rob.

  222. Ideal Says:

    Dear Rob

    I see in your script of calculating the demappe exit curve that you wrote
    N0 = 1/(SNR_linear), then in the channel model sigma^2 = (No/2) and in the demodulation No according to the pdf of n. But I am not sure where you define the code rate R?

    I think, sigma^2 = (2RmRc(EbNo_Linear))^-1, where for QPSK Rm=2 and Rc is the code rate. Because ten Brinks define the demapper EXIT curve Ie = J(sqrt(8Rc(EbNo_Linear))) for gray mapping in his paper “Design of low density parity check code for modulation and detection” equation (19) and plot the results in Fig. 6 for 1X1. It gives different result from your demapper script. Can you please comment? Thanks

  223. Rob Says:

    Hi Ideal,

    There is a difference between SNR and Eb/N0 - I am using SNR. The relationship between them is Eb/N0 (dB) = SNR (dB) - 10*log10(R*log2(M)), where R is the channel coding rate and M is the number of constellation points, e.g. M=4 in QPSK.

    Take care, Rob.

  224. Ideal Says:

    Dear Rob,

    Thanks, it means that I can replace N0 with (R*log2(M)*EbNo_Lin)^-1 in your script of soft_demodulate in order to represents it in Eb/No. I think I am right now? Thanks again

  225. Rob Says:

    Hi Ideal,

    That looks correct to me.

    Take care, Rob.

  226. Ideal Says:

    Dear Rob,

    Thanks but I have again a basic question please.

    Actually for symbol mapping like QPSK/4PAM, we write the symbol energy as Es = 1/M(\sum|x|^2) in electrical domain and Es = 1/M(\sum|x|) in optical domain and Eb/No = (1/R*log2(M)) * Es/No, My confusion is that, when we define No, we simply write No=(R*log2(M)*Eb/No)^-1, where is the value of Es?

    I was thinking in BPSK Es = 1, that’s why we don’t need to write it but for the case of QPSK/4-PAM, Es will not be 1 or I am wrong. Please can you rectify me. Thanks a lot

  227. Rob Says:

    Hi Ideal,

    Typically, people design all of their modulation schemes to have Es = 1. For example, in QPSK we multiply the constellation points by 1/sqrt(2), in order to make Es = 1. In 16QAM, we multiply the constellation points by 1/sqrt(10) to achieve this.

    Take care, Rob.

  228. Ideal Says:

    Dear Rob,

    Thanks for answering. I am thinking to do some derivations for natural mapping, in order to calculate the EXIT chart. can you give me any advice in matter please? Thanks

  229. Rob Says:

    Hi Ideal,

    The first step is to calculate the probabilities P(y|x) for each constellation point x, where y is the received signal. After that, you can convert this into a probability for each bit value.

    Take care, Rob.

  230. Ideal Says:

    Dear Rob,

    It looks quite OK. I think if I calculation the conditional probabilities for each constellation point assuming the AWGN channel for each constellation point. the second point I didn’t understand, like why should I need to convert the conditional probabilities into a probabilities for each bit? can you elaborate it bit more please. or any reference, from where I can have a start-up please please. Thanks

  231. Rob Says:

    Hi Ideal,

    You need to calculate probabilities for each bit because you want to obtain LLRs for each bit. References on BICM-ID will give you the mathematics behind all this.

    Take care, Rob.

  232. Elnaz Says:

    Hi Rob,

    I was wondering if there is a known-to-be best performing equalizer the same way as we have LDPC code as the best performing coding strategy?
    Basically, I am convolving a matrix of coded bits with a 2-D pulse shape which introduces ISI in both dimensions and I need to use equalizer to mitigate the problem.

    Thanks,
    Elnaz

  233. Rob Says:

    Hi Elnaz,

    Non-linear equalisers are the best performing. A good example is a turbo equaliser, which uses the BCJR algorithm.

    Take care, Rob.

  234. Elnaz Says:

    Hi Rob,

    I will be doing joint iterative decoding, timing recovery, and equalization. I have done the first two but I don\’t know how should I combine my Turbo-decoder (BCJRs) to include equalizer (Turbo with BCJR) as well. Are there any resources or codes that I can benefit from? What do you suggest?

    Thanks,
    Elnaz

  235. Ideal Says:

    Dear Rob,

    I am still not clear how to start calculating the analytical derivation of EXIT chart for natural QPSK mapping. Please elaborate it bit more. Thanks

  236. Rob Says:

    Hi Elnaz,

    My advice would be to keep the turbo equaliser separate from the other system components. You can then connect the various system components through interleavers and then perform iterative decoding among them all.

    Take care, Rob.

  237. Rob Says:

    Hi Ideal,

    I didn’t realise that you are trying to derive an analytic expression for the EXIT function of the QPSK demapper. I’m afraid that I’ve only ever considered the simplest of cases for analytic EXIT functions (namely LDPC variable and check node decoders) - so I don’t know where to get started with this. It looks like this reference may be of use to you though…
    http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4114253&tag=1

    Take care, Rob.

  238. Elnaz Says:

    Hi Rob,

    I know that there are 3 blocks of timing recovery, Turbo decoder, and Equalizer which should iterate together. What I don’t know is that how should I exchange the output llrs between the decoder and the equalizer. Should I exchange extrinsic llrs or full llrs? and how?
    Also, I am under the impression that “Turbo Equalizer with BCJR” is the same “Turbo decoder” I already have with the only difference that in the equalizer we output the llrs for the coded bits instead of the llrs for the message bits. Am I correct? Or the equalizer is totally something else?

    Thanks a lot,
    Elnaz

  239. Elnaz Says:

    Dear Rob,

    This old paper,
    read.pudn.com/downloads144/doc/comm/626085/a2.pdf, seems to be doing exactly that. But instead of keeping the turbo equalizer separate, it combines turbo decoder with an equalizer to build a turbo equaliser.

    More important, my concern is that since I don’t have access to the channel transfer function (my channel is when I “2-D convolve” a matrix of coded bits with a 2-D pulse shape), how can I use BCJR in my equalizer since I don’t have the trellis of the channel?

    Thanks,
    Elnaz

  240. Ali Says:

    Hello Dear Rob,
    I want to use a general turbo code (which uses M-QAM or M-PSK) in a system, when space-time coding is used too. Channel is Rayleigh fading.
    Could you please guide me?
    Best Regards
    ALI

  241. Rob Says:

    Hi Ali,

    The turbo code that is provided here is compatible with M-ary space-time coding, although I’m afraid that I don’t have any Matlab code for the latter. You just need to build a space-time encoder that accepts bits from the turbo encoder and a space-time decoder that provides corresponding LLRs for the turbo decoder.

    Take care, Rob.

  242. Rob Says:

    Hi Elnaz,

    “how should I exchange the output llrs between the decoder and the equalizer. Should I exchange extrinsic llrs or full llrs? and how?” You should exchange extrinsic LLRs that pertain to the turbo-encoded bit sequence. In order to obtain this, you will need to modify component_decoder.m so that it also outputs extrinsic_encoded_llrs. Also, you will need to obtain extrinsic LLRs for the systematic bits by adding the uncoded_extrinsic_llrs that are provided by both component decoders. Finally, the last three bits in the extrinsic_uncoded_llrs can be extracted to give you extrinsic LLRs for the termination bits.

    “Or the equalizer is totally something else?” The equalizer should exploit knowledge about the dispersion in the channel to recover LLRs about the transmitted bits. It can represent the dispersion using a trellis and apply the BCJR algorithm to get the LLRs.

    If your receiver does not have knowledge of the channel dispersion then you will not be able to use an equaliser unless you use channel estimation to obtain this knowledge.

    Take care, Rob.

  243. Elnaz Says:

    Hi Rob,

    I see. Therefore, turbo equaliser is/cen be an equaliser + turbo decoder combined with turbo principle.
    My question, therefore, boils down to “how can I transfer my channel into a trellis?”. All my channel is doing is convolving a matrix of coded bits with a 2-D pulse shape. I have the pulse shape but I do not know how to convert it to a transfer function in a suitable form that can be translated into a trellis.
    Is there a way to do this?

    Thanks,
    Elnaz

  244. Ali Says:

    Hello dear Rob
    Thanks for your help. where is that file? Does it have adjustable rate?
    Best Regards
    Ali

  245. Rob Says:

    Hi Elnaz,

    You need a trellis having M^(T-1) states, where M is the number of constellation points you are using and T is the number of consecutive received symbols that are affected by a particular transmitted symbol. There should be M number of transitions that emerge from each state and M number of transitions that merge into each state.

    The trellis I have described is shown in the following paper, where L = T-1…
    http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1267050

    Take care, Rob.

  246. Rob Says:

    Hi Ali,

    You can download my turbo code from…
    http://users.ecs.soton.ac.uk/rm/wp-content/matlabturbo.zip

    This doesn’t have an adjustable rate, but you could modify it to do this by using puncturing or by repeating some of the encoded bit sequences.

    Take care, Rob.

  247. Ali Says:

    Hi Prof. Rob,
    Thanks for your attention
    Best Regards
    Ali

  248. Ali Says:

    Hi Prof.Rob
    Could you please give me a Code that achieves to capacity (or closely near to capacity, like LDPC code). If MATLAB code is available, please give me.
    Best Regads
    Ali

  249. Ali Says:

    Excuse me, which algorithm does your code follow? log-MAP, max log-MAP or another one?
    Thanks
    Ali

  250. Ali Says:

    hi Dear Prof.
    Excuse me, I have another question:
    Let, we have two space-time code. First code achieves better capacity than the second one., but in a state, the second code has better BER. Now, we want to use a strong outer channel coder. Can we say that because first code has better capacity in all SNRs, we can use a good channel encoder to proof this claim?

  251. jack Says:

    Hi Rob,
    why does a turbo encoder work worse than a LDPC code?
    thanks

  252. Rob Says:

    Hi Ali,

    I have some Matlab code for drawing the EXIT chart of an LDPC at…
    http://users.ecs.soton.ac.uk/rm/resources/matlabturbo/#comment-10965
    …you can modify this to build an LDPC decoder.

    My Matlab code for the turbo decoder can use the Log-MAP, Appox-Log-MAP (which uses a lookup table to approximate the Jacobian logarithm) and the Max-Log-MAP. You can choose between these by modifying jac.m

    The space-time code that offers the greatest channel capacity is the one that can give the best performance when combined with a convolutional code.

    Take care, Rob.

  253. Rob Says:

    Hi Jack,

    The relative advantages and disadvantages of LDPC and turbo codes is a matter of debate. My opinion is that because LDPC codes have longer interleavers than the equivalent turbo codes, the LDPC designer has more design choices to make, yielding a greater opportunity to find a good design.

    Take care, Rob.

  254. Elnaz Says:

    Hi Rob,

    I have a question about how to use your BCJR decoder as an equalizer.
    Say, the channel model (pulse shape) is a vector of 5 coefficients which makes a 4-tap delay line. How should I change your transition matrix to include this coefficients in the tap-delay line?

    Thanks,
    Elnaz

  255. Rob Says:

    Hi Elnaz,

    The transition matrix should have M^T number of rows. Each row should one column for the from state, one column for the to state and T number of columns that list every possible combination of T constellation points. The from state depends on the first T-1 constellation points and the to state depends on the last T-1 constellation points. You also need log2(M) number of columns to list the bits that are mapped to the last of the T constellation points.

    Take care, Rob.

  256. Elnaz Says:

    Hi Rob,

    I know how your code and transition matrix works for the decoding job. What I was asking is how should I change your code to be an equalizer instead of a receiver? Could you please explain what parts of the code should be changed? For example, what are the uncoded_apriori_llrs here since all the bits are channeled and there are no systematic bits to use for this purpose.

    Thanks,
    Elnaz

  257. Rob Says:

    Hi Elnaz,

    The calculation of alphas, betas, deltas and extrinsic llrs should remain very similar to how they are now. The big change will be in the calculation of the gammas.

    Take care, Rob.

  258. Ali Says:

    Hello dear Rob,
    Thank your for your constructive expressions. Excuse me, How can I change your matlab code for turbo code to M-ary modulations. you have presented these sentences:
    % BPSK demodulator
    % These labels match those used in Figure 2.11 of Liang Li\’s nine month report.
    a_c = (abs(a_rx+1).^2-abs(a_rx-1).^2)/N0;
    c_c = (abs(c_rx+1).^2-abs(c_rx-1).^2)/N0;
    d_c = (abs(d_rx+1).^2-abs(d_rx-1).^2)/N0;
    e_c = (abs(e_rx+1).^2-abs(e_rx-1).^2)/N0;
    f_c = (abs(f_rx+1).^2-abs(f_rx-1).^2)/N0;
    What will be new commands?
    Thanks alot

  259. Rob Says:

    Hello Ali,

    Anything higher than M=2 becomes a lot more complicated that these equations. You can download a soft demodulator for higher order modulation from…
    http://users.ecs.soton.ac.uk/rm/wp-content/QPSKEXIT.zip

    Take care, Rob.

  260. Elnaz Says:

    Dear Rob,

    Please correct me if I’m wrong. Transferring BCJR decoder into an equalizer, I have my transition matrix for 16 states and the encoded bits here are numbers in 0:16 range (there is no feedback path; so generating the transfer matrix is a lot easier and can be done automatically). Therefore, I think, I no longer can do log(P0/P1) normalization when calculating encoded-gammas the way you’ve done.
    However, I think, I calculate |channeloutput-encoded bit|^2 /(2*variance) for each row of my transition matrix separately; and then, add those values that correspond to uncoded bit=0 in prob0 and the rest in prob1 and that should do it. Everything else stays the same. What do you think? Correct?

    Elnaz

  261. Rob Says:

    Hi Elnaz,

    Nothing that you have said here seems wrong to me - my suggestion would be to build it and then test it by comparing the EXIT curves obtained using the averaging and histogram methods - these should match each other.

    Take care, Rob.

  262. Elnaz Says:

    Hi Rob,

    I have changed:
    \"if transitions(transition_index, 4)==0
    encoded_gammas(transition_index, bit_index) = apriori_encoded_llrs(bit_index);
    end\"

    to

    \"encoded_gammas(transition_index, bit_index) = -(encoded_input(bit_index)-transitions(transition_index,4))^2/(2*sigma2); \"
    which is calculated for all the lines in the transitions matrix.

    Also, I\’ve changed the transitions matrix according to the figure 4 in the paper you referred earlier. These are the only changes I\’ve made to convert the BCJR decoder into an equalizer. Also, I\’ve set apriori_uncoded-llrs to all zeros.

    Now, I expect that if I pass an stream of bits(-,+1s) through the channel (convolve the bits with E2PR2 h = [1 4 6 4 1]) and then add the noise and then through the equalizer, the extrinsic_uncoded_llrs from the equalizer should have the same sign as of the original message bits. I think even before going to BER or EXIT plots, this simple sign check can show if the equalizer is working.
    I don\’t get the result I expect i.e. the signs don\’t match.

    Do you know what might be wrong? How can I debug? Have I done correctly so far you think?

    Thank you,
    Elnaz

  263. Rob Says:

    Hi Elnaz,

    Your encoded_gammas needs to be a function of not only the constellation point in transitions(transition_index,4), but also the constellation points that relate to the previous symbol periods.

    The reason why the signs may not be matching could be because you have strong dispersion. To do your test properly, you may like to remove dispersion - this will effectively transform your equaliser into the soft demodulator of…
    http://users.ecs.soton.ac.uk/rm/wp-content/QPSKEXIT.zip

    Take care, Rob.

  264. Elnaz Says:

    Dear Rob,
    I did not understand the first part. Did you mean that my calculation for encoded_gammas is wrong? I am putting the power in the exponential term as my encoded_gammas for each line in the transitions matrix separately, i.e. I calculate |channeloutput-encoded bit|^2 /(2*variance) for each row of my transition matrix separately (channeloutput is simply the ISI-channeld output).
    In your comment before the last one, you mentioned it was correct. Have I missed something?

    Thanks,
    Elnaz

  265. Rob Says:

    Hi Elnaz,

    You only have one encoded gamma, not one per column in the transitions matrix. This is because you only have one received symbol.

    I’m afraid that I must refer you back to for a clearer explanation…
    http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1267050

    I don’t think that I will be able to explain it any better than the example given in Figure 5 of that paper.

    Take care, Rob.

  266. Elnaz Says:

    Hi Rob,

    I am testing my BCJR equaliser with channel response E2PR2 (h=[1 4 6 4 1])).
    The part that I do not understand is that I should discard the last 4 extrinsic_uncoded_llrs to get the signs match. If it is because of the zero-padding that the convolution in MATLAB does then I had to discard the first and last 2 numbers rather than the last 4.
    I am trying this with both termination on and off cases and it does not make a difference (I am testing with no encoder just randn BPSK bits). Also, there is no additive noise here.
    Also, even after discarding the last four, sometimes the first bits are incorrect. All the rest match.

    Do you know why this is so?

    Thank you,
    Elnaz

  267. Rob Says:

    Hi Elnaz,

    I’m afraid that I don’t know why this is - I’ve never actually programmed a turbo equaliser myself. Sorry for not being much help.

    Take care, Rob.

  268. Elnaz Says:

    Hi Rob,

    It’s alright. You’ve been a great help so far.
    Do you know of a reference for BER plot for a BCJR equalizer for EEPR2 response? I’ve searched a lot and I was not able to find any.

    Thanks,
    Elnaz

  269. Rob Says:

    Sorry Elnaz, I’m afraid that I don’t know where to find that BEE plot. Take care, Rob.

  270. Belal Says:

    Dear Rob

    Please if possible , can you provide me the code of the turbo code with DS-CDMA or WCDMA and the documentation of this work, because it is very important.

    Thank you,
    Belal

  271. Rob Says:

    Hello Balal,

    I’m afraid that I don’t have any code for CDMA.

    Take care, Rob.

  272. Belal Says:

    Dear Dr Robe,

    Thank you for all help,
    And if possible, can i insert spreading code “walsh code” in to your code of UMTS with turbo code, becuase this work is a part of the requirements of my master thesis.

    Thank you for all help,
    Kind Regard,
    Belal

  273. Rob Says:

    Hi Belal,

    It would certainly be possible to combine my turbo code with a Walsh spreading code. However, I’m afraid that I don’t have any Matlab code to do this.

    Take care, Rob.

  274. Ideal Says:

    Dear Rob,

    I have one simple question about the QPSK demapper EXIT chart using the natural mappings (b_1,b_0) –> X(QPSK Symbol). Example

    1. I have input bits for the QPSK mapper (b_1,b_0) mapp–> QPSK Symbol (using natural mapping).

    2. add noise and transmit.

    3. At the receiver I try to find the extrinsic llr of bit b_1 –>e_llr(b_1) which needs a priori information from bit b_0 –>a_llr(b_0).

    But I see your QPSKEXIT chart script, you are generating an input random vector (a) and converting it into QPSK symbols and at the demapper you are demapping, i.e., calculating the extrinsic llr –> e_llr(a) with the a priori llr –>a_llr(a). I am confuse here that where can I relate the e_llr(b_1) and a_llr(b_0),

    and on the other way around, you know that If I want to calculate the extrinsic llr of bit b_0, e_llr(b_0), I need a priori llr of bit b_1, a_llr(b_1), what will be the difference in this regards in your script in both way?.

    can you please highlight this concept? Thanks and kind regards

  275. Rob Says:

    Hi Ideal,

    In soft_demodulate.m we have…
    function extrinsic_llrs = soft_demodulate(apriori_llrs, rx, channel, N0)

    Here apriori_llrs is a vector containing [a_llr(b_0), a_llr(b_1)] and extrinsic_llrs is a vector containing [e_llr(b_0), e_llr(b_1)].

    Take care, Rob.

  276. Ideal Says:

    Dear Rob,

    Thats right and now if I want to calculate the extrinsic llr e_llr(b_1) with the a priori llr a_llr(b_0), then how can I separate these vectors conditioning on each other. Like I want the output extrinsic llr e_llr(b_1) given the a priori llr a_llr(b_0) or the extrinsic llr e_llr(b_0) given the a priori llr a_llr(b_1).

    Thanks for your responses :)

  277. Rob Says:

    Hi Ideal,

    If you look closely at soft_demodulate.m, you will see that e_llr(b_1) is calculated based only on a_llr(b_0). Here, a_llr(b_1) does not affect this calculation. This is achieved using the following if statement…
    if bit_index2 ~= bit_index

    So, my Matlab code is already doing what you are asking for.

    Take care, Rob.

  278. Ideal Says:

    Dear Rob,

    Thanks for that, now I got it. It means, if I want to see the extrinsic llr e_llr(b_0), I can extract the odd terms in extrinsic_llrs vector containing [e_llr(b_0), e_llr(b_1)] and even terms for e_llr(b_1). Am I right now?

    and as you said the e_llr(b_1) is calculated based only on the a_llr(b_0) then in this way, I can see the histogram of e_llr(b_1) based on a_llr(b_0) and can calculate the extrinsic mutual information of the extrinsic llr.

    I am really thankful for all your help. You are so great :)

  279. Rob Says:

    Hi Ideal,

    It looks like you’ve got it figured out now.

    Take care, Rob.

  280. Ideal Says:

    Dear Rob,

    Thanks for the responses.
    Now I want to compare the histogram of e_llr(b_1) given a_llr(b_0) with the normal pdf and want to see if these two fits.

    I think, in order to perform these comparison, at first I can calculate the histogram of e_llr(b_1) using the hist function of matlab and then hold the plot and then using the normpdf(vector, mean(e_llr(b_1),0.5*mean(e_llr(b_1))) matlab function I can see if these two plots fit.

    Am I right or give me any suggestion please? :) Thanks

  281. Rob Says:

    Hi Ideal,

    That sounds right to me.

    Take care, Rob.

  282. Ali Says:

    Hi Dear Prof.
    Before two weeks ago, I wanted QPSK modulation for turbo coded system. and you proposed me this file:
    http://users.ecs.soton.ac.uk/rm/wp-content/QPSKEXIT.zip
    How can I see the BER performance of this system?
    Thanks for your help
    Ali

  283. Rob Says:

    Hi Ali,

    For this QPSK scheme to fulfil its full potential, you should concatenate it with some kind of soft-in soft-out channel code. You could use the outer code from…
    http://users.ecs.soton.ac.uk/rm/resources/matlabexit/
    This will give you bit-interleaved coded modulation with iterative decoding (BICM-ID).

    Take care, Rob.

  284. Yue Says:

    Hi Rob,

    I have some questions:

    1. If I have the extrinsic LLRs of the decoder E=(E1,E2,…En), how to estimate the pdf p(E=Ei|x=-1) and p(E=Ei|x=+1) using a histogram of E?

    2. How to determine the range and the bin width of the histogram?

    3. After p(E=Ei|x=-1) and p(E=Ei|x=+1) have been calculated, how to get the mutual information Ie=I(E;X)?

    Thank you very much!

    Yue

  285. Tui Says:

    Hi, I have some question.
    If I select the different bins, the Ie has large different value?
    If I select the smaller bin, Ie could be more accurate?
    Thank you!

  286. Rob Says:

    Hello Yue,

    1. You can do this using my Matlab code at…
    http://users.ecs.soton.ac.uk/rm/resources/matlabexit/#comment-246

    2. My code will do this automatically for you. There is some discussion about how this is done at…
    http://users.ecs.soton.ac.uk/rm/resources/matlabexit/#comment-158

    3. You can do this using measure_mutual_information_histogram.m, which you can download from above.

    Take care, Rob.

  287. Rob Says:

    Hi Tui,

    This requires a careful optimisation - if the bin width is too small or too big, the MI will be measured inaccurately. I do it by determining the bin width automatically, as discussed in my comment to Yue, immediately above.

    Take care, Rob.

  288. Ideal Says:

    Dear Rob,

    I want to plot the histogram of the extrinsic llr and see either it is normal distributed or not?

    Usually using your display_llr_histogram() function, I can see the distribution of the two bits in llr but when i want to plot histogram over this plot, it doesn’t plot well.
    please give me advise what should I need to do? In the previous comments I told you about it but I see that doesn’t give me the right results.

    Actually I want to plot like you script is giving the results of two bits in one llr but with histogram comparison. Thanks

  289. Tui Says:

    Dear Rob,

    Thank you for your reply.

    I still have some questions:

    1. I notice that you use the numerical integration to calculate I_E which is an integration. Why don’t you multiply bin_width in accumulation for calculating I_E in program “measure_mutual_information_histogram.m”?

    2. If the encoded sequence is an all zero sequence instead of round(rand(1,n)), how to use your program “measure_mutual_information_histogram.m” to calculate Ie giving E={E1,E2,…,En}?

    Thank you again!

  290. Rob Says:

    Hi Ideal,

    I’m not sure why you want to plot a histogram over the plot that display_llr_histogram() gives you - this plot is already the histogram of the LLRs.

    I think that you want to plot the histograms for the two QPSK modulated bits separately. In which case, you need to arrange the LLRs and the bits into two groups and then give each of these to display_llr_histogram() separately.

    Take care, Rob.

  291. Rob Says:

    Hi Tui,

    1. I can’t remember the specific reason for this but I remember there an important one. Perhaps this is because the bin width gets cancelled out by something else. In any case, the histogram method doesn’t work if we multiply by the bin width…

    2. measure_mutual_information_histogram.m assumes that the values of the bits are equiprobable, i.e. that the bit sequence contains an equal number of 0s and 1s. So it doesn’t work when all of the bits are 0s. Here are some versions that work when the bit sequence does not contain an equal number of 0s and 1s…
    http://users.ecs.soton.ac.uk/rm/wp-content/measure_MI_averaging_generalised.m
    http://users.ecs.soton.ac.uk/rm/wp-content/measure_MI_histogram_generalised.m
    Note however, that when all the bits are zero, the MI will come out as zero. You should also note that these methods assume that the LLRs know that the bit values are not equiprobable. i.e. in the absence of any information, the LLRs should have values of ln(p0/p1), rather than values of 0.

    Take care, Rob.

  292. Yue Says:

    Dear Rob,

    I have a question to your comment 2 to Tui. Sometimes, we can sent all zero codewords, in that case the process of encoding can be cut down. According to the symmetric pdf of E, we have that p(E=Ei|x=+1)=p(E=-Ei|x=-1). Therefore, we can estimate p(E=Ei|x=+1) using histogram, and also get p(E=-Ei|x=-1) as well. Is it okay?

    Besides, I want to ask you another questions:
    1. If the length of code is too small, such as 11, I think that it is not accurate to calculate p(E=Ei|x=+1) and p(E=-Ei|x=-1) using histogram. How to deal with it?

    Thank you very much!

  293. Rob Says:

    Hi Yue,

    This will only work if a number of conditions are met:
    - your code needs to be linear and symmetrical
    - your modulation scheme needs to be symmetrical

    In general, I would not recommend this approach. I would always generate random messages, rather than all-zero messages.

    If the length of each frame short, you can simulate a number of frames and then concatenate them together. Then you can use the histogram method on the long concatenated sequence.

    Take care, Rob.

  294. Ideal Says:

    Dear Rob,

    I want to plot the histogram after puncturing symbols and want to see that whether after puncturing, the pdf of LLR is still normal. That’s why I was trying to see the histogram plot and display_llr_histogram plot over each other and by this I can confirm that the llr is Normal after puncturing or not.

    This was the objective behind. But I am not sure I was doing right or wrong? Thanks

  295. Elnaz Says:

    Hi Rob,

    Could you please explain how best I can list the error patterns in a certain order, given the generator matrix, for syndrome decoding. Basically, I want to do what \"syndtable\" in MATLAB does but in a simpler way.

    Thanks,
    Elnaz

  296. Rob Says:

    Hi Ideal,

    I see - you want to compare before and after histograms. I think that this sounds reasonable. My expectation is that if you are using random puncturing, the two histograms will be very similar.

    Take care, Rob.

  297. Rob Says:

    Hi Elnaz,

    If the generator matrix is not too big, the simple way is to build a list of every possible input into the encoder and then use this to obtain every possible output. Then, for each possible pairing of outputs, you can do an XOR to get the error pattern.

    Take care, Rob.

  298. Elnaz Says:

    Hi Rob,

    Do you know how can I generate a Hamming code parity check matrix (with parameter m) in systematic format? Basically, I’m trying to do what “hammgen” of MATLAB does in a simpler way.

    Thanks,
    Elnaz

  299. Ali Says:

    Hi dear prof.
    I want to use LTE intelreaver, how will be the MATLAB code after considering this matter, to find BER?
    Best regards

  300. Rob Says:

    Hi Elnaz,

    I’m afraid that I don’t know of any simpler way than hammgen…

    Take care, Rob.

  301. Rob Says:

    Hi Ali,

    All you need to do is replace the mentions of get_UMTS_interleaver in main_ber with get_LTE_interleaver. You can download get_LTE_interleaver.m from…
    http://users.ecs.soton.ac.uk/rm/wp-content/get_LTE_interleaver.m

    Take care, Rob.

  302. Ali Says:

    Hi dear Prof.
    What is the range of LTE interleaver?
    Are you sure that the other parts of MATLAB code are the same as the MATLAB code for UMTS interleaver?
    Best Regards
    Ali

  303. Rob Says:

    Hi Ali,

    The shortest LTE interleaver is 40 bits, the longest is 6144 bits. The other parts of the LTE turbo code are the same as in UMTS. To see this for yourself, you can take a look in the documentation for the standards in the links at the top of this page.

    Take care, Rob.

  304. Ideal Says:

    Dear Rob,

    How can I use your modulate and soft_demodulate scripts for higher order mapping schemes like 16-QAM or 64-QAM?
    and how can they be implemented in simulations, like for 16-QAM, each symbol has four bit, then how can I replace it in your script of calculating demapper exit curve, where you write modulate(a(start:stop)) and a_e(start:stop) = soft_demodulate(.) for QPSK (2 bits per symbol); :(

    I appreciate your help. Thanks

  305. Rob Says:

    Hi Ideal,

    All you need to do is modify the constellation_points and bit_labels - every thing else is automatic.

    In main_exit, you just need to change bit_count.

    Take care, Rob.

  306. Ali Says:

    Hi dear Prof.
    Excuse me, I don’t know about channel Coding very much. Could you please help me to puncture your turbo code to rate 1/2.
    I thank you for your lats helps.
    Bests Ali

  307. Rob Says:

    Hi Ali,

    You can see how to implement puncturing at…
    http://users.ecs.soton.ac.uk/rm/resources/matlabturbo/#comment-8929

    Take care, Rob.

  308. Ideal Says:

    Dear Rob,

    Thanks for all your support. I again has one tricky question please.

    Lets I got one demapper curve (y) for a particular SNR, i.e.
    y = ax^3 + bx^2 + cx + d, SNR = 1dB, x=0:0.1:1 (a-priori MI), (a,b,c,d=constants).
    It means I have three different variables, y,x,SNR. I need to store a large number demapper equations for a range of SNRs and want to utilize them somewhere else. How can I use interpulation in matlab function which can cover three parameters in which x and y are vector but SNR is number? I though I can use interp2 but not sure how to use it?

    Please do you have any idea about this problem? Thanks a lot

  309. Rob Says:

    Hi Ideal,

    I’m afraid that I’ve never done that sort of thing before, so your guess is as good as mine…

    Take care, Rob.

  310. Elnaz Says:

    Hi Rob,

    I have a question about the PLL with Mueller-Muller estimate. Do you know how it works?

    Thanks,
    Elnaz

  311. Rob Says:

    Hi Elnaz,

    I’m afraid that I have never worked on PLLs, so I can’t help you with this.

    Take care, Rob.

  312. Ideal Says:

    Dear Rob,

    Thanks for the fruitful discussion. I have very basic question please.
    If I am considering the real valued 4-PAM constellation, i.e.,
    constellation_points = [-1; -1/3; 1/3; 1]/sqrt(5/9); and the received signal is represented by y = Px + n; with P is the received signal power and n is the AWGN noise with zero means and unit variance noise. In that case, can I replace N0 = 1 in your soft_demodulate.m? Thanks

  313. Rob Says:

    Hi Ideal,

    You should use…
    constellation_points = sqrt(P)*[-1; -1/3; 1/3; 1]/sqrt(5/9);
    y= x+n;
    N0 = 1;

    Take care, Rob.

  314. Ideal Says:

    Dear Rob,

    I don’t understand why did you write sqrt(P);
    The symbol energy of the system considering optical to electrical domain is
    Es = P^2(5/9), for the constellation_points = [-1; -1/3; 1/3; 1];, where P is the optical transmit power and considering the zero mean unit variance noise, The SNR=P^2(5/9);

  315. Elnaz Says:

    Hi Rob,

    Could you please explain a stopping criteria for turbo decoder or actually for turbo equalizer when applied in a iterative receiver scheme?

    Thanks,
    Elnaz

  316. Elnaz Says:

    Hi Rob,

    Regarding my previous question, I’m using sum of LLRs for the stopping criteria. What do you think?
    My new question:
    I am simulating Turbo equalizer on a E2PR2 channel. I need to somehow convert the LLR outputs of the Turbo equalizer back to the channeld format. Right now I am taking the hard estimate (sign) of those LLRs and modulate them back again with the channel response which is not the optimum thing to do. How can I do this properly?

    Thank you,
    Elnaz

  317. Rob Says:

    Hi Elnaz,

    I normally stop the iterative decoding process when the mutual information of the extrinsic LLRs stops improving.

    It would be possible to modify the turbo equaliser so that it not only outputs extrinsic information about the bits, but also extrinsic information about the modulated symbols. This would be more optimal than modulating a hard decision for the bits…

    Take care, Rob.

  318. Rob Says:

    Hi Ideal,

    This square root is needed because amplitude is related to the square root of power. Here, P is relating to power, while x, y, n and sqrt(P) are all related to amplitude…

    Take care, Rob.

  319. Elnaz Says:

    Hi Rob,

    Could you explain a bit more how should I modify the turbo equalizer to output information on the modulated bits?

    Thanks,
    Elnaz

  320. Elnaz Says:

    Please add this to my previous comment:
    Also, how should I change the LLRs into soft channel outputs?

  321. Rob Says:

    Hi Elnaz,

    This is easiest for BPSK, in which case the LLRs for the BPSK modulated symbols are equal to the LLRs for the bits. In the case of a higher order modulation scheme, you just need to output the symbol probabilities that are calculated during the turbo equalisation algorithm.

    Take care, Rob.

  322. Elnaz Says:

    Hi Rob,

    What I meant to ask is that should I follow the same procedure that I used to get the encoded outputs from component_decoder in my BCJR equalizer as well i.e. to add the lines:
    deltas2(transition_index, bit_index) = alphas(transitions(transition_index,1),bit_index) + uncoded_gammas(transition_index, bit_index) + betas(transitions(transition_index,2),bit_index);

    And,

    prob1 = jac(prob1, deltas2(transition_index,bit_index)); (I don’t think I can do this since the outputs are no longer 0s and 1s but some integer values)

    Then, if correct, this will give me the extrinsic llrs for modulated bits?
    Then, I can’t change these llrs to normal channel output format by simply dividing them by 2/sigma2 i.e. the way to go in case of decoder but not equalizer. My channel is E2PR2 response applied on BPSK symbols. Then I’m wondering how can I extract channel output from llr-outputs of my turbo equalizer.

    Thanks,
    Elnaz

  323. Rob Says:

    Hi Elnaz,

    I think that you are on the right track here. For each of the M symbol values (e.g. M = 4 in QPSK), you can use an equation that is similar to the prob1 equation that you have provided. The exponential of these prob values will give you values that are proportional to symbol values. You just need to normalise these values in order to get the correct probabilities.

    Take care, Rob.

  324. Elnaz Says:

    Hi Rob,

    Do you mean summing over delta2s corresponding to each row in the transition matrix and then for example prob4 = exp(sum of delta2s corresponding to output=4)/sum of delta2s for all output values?

    Thanks,
    Elnaz

  325. Rob Says:

    Hi Elnaz,

    That sounds right to me.

    Take care, Rob.

  326. Elnaz Says:

    Hi Rob,

    One additional question:
    My simulations run verry slowly and according to MATLAB profiler, “conv” and “jac” commands are the major consumers. What can I do to make “jac”run faster?

    Thanks,
    Elnaz

  327. Rob Says:

    Hi Elnaz,

    If you look into jac.m, you’ll see that it has three possible modes of operation. I would suggest using the second mode, which approximates the exp and log functions using a look up table.

    Take care, Rob.

  328. Elnaz Says:

    Hi Rob,

    As you know I am using your BCJR component_decoder as an equalizer after making some changes of course. However, I can’t use the code for long stream of bits e.g. 32 kbit in MATLAB. I get out of memory problem and it takes a long long time to equalize say 15 kbits. Is there anyway I can improve the code or the speed of its execution?

    Thanks,
    Elnaz

  329. Rob Says:

    Hi Elnaz,

    The sliding window technique can be used to reduce the memory requirement of a BCJR decoder. You can read about this technique in…
    http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4726112&tag=1

    Take care, Rob.

  330. Sam Says:

    Hi Rob,

    Thanks for all your answers, they are really useful and helped me understand much more how you obtained the results.

    To my understanding, your results are for a AWGN channel.

    Assume we add Rayleigh fading as defined below :

    n = 1/sqrt(2)*[randn(1,N) + j*randn(1,N)]; % AWGN o db variance
    h = 1/sqrt(2)*[randn(1,N) + j*randn(1,N)]; % Rayleigh channel

    % Channel and noise Noise addition
    y = h.*s + 10^(-Eb_N0_dB(ii)/20)*n;

    Is there anything we have to change in the BPSK demodulator ?
    What about the BCJR decoder ?

    Thanks again for your help, very useful.

    Regards

  331. Rob Says:

    Hello Sam,

    Only the demodulator needs to be updated. The updated code should look like…
    a_c = (abs(a_rx+h).^2-abs(a_rx-h).^2)/N0;

    Take care, Rob.

  332. Sam Says:

    Hi Rob,

    I’ve tried that, and it’s not giving me very accurate results for BER vs ebno. I also changed frame length to 4000 instead of 40 and result remained the same.
    Actually my curve is going up and down, it’s not a stable one. I wonder why.

    As a reference, i get to a BER value of 0.01 for 10 dB.

    I was wondering if i had to modify something else in the decoder, like for the calculation of gammas, alphas or betas ?

    Thanks for your help,

    Regards

    Sam

  333. Rob Says:

    Hi Sam,

    You don’t need to modify anything else. My suggestion is for you to test each component of your scheme separately. This will help you to determine if the problem is in your encoder, modulator, channel, demodulator, decoder, etc.

    You can do this by drawing the EXIT curves for each component using both the averaging and the histogram methods. These two methods will give similar curves if everything is working okay. If not, then this will identify which component has the problem.

    Take care, Rob.

  334. Sam Says:

    Hi Rob,

    In order to test it, i have used the same code as yours, i added the rayleigh and modified the part for the demodulator BPSK as you mentionned :

    a_c = (abs(a_rx+h).^2-abs(a_rx-h).^2)/N0;

    instead of

    a_c = (abs(a_rx+1).^2-abs(a_rx-1).^2)/N0;

    But that doesn\’t work neither.

    I am still trying to figure out what isn\’t working,

    What do you think ? Weird part is without Rayleigh, all works just fine.

    Thanks again for your help,

  335. Rob Says:

    Hello Sam,

    You may like to try using the modulator and demodulator that can be downloaded from…
    http://users.ecs.soton.ac.uk/rm/resources/matlabexit/#comment-1545

    This code demonstrates how to use the demodulator in the case of a Rayleigh fading channel. You can convert the modulator and demodulator into BPSK by replacing the corresponding lines of code with…
    constellation_points = [+1;-1};
    bit_labels = [0;1];

    Take care, Rob.

  336. Ideal Says:

    Dear Rob,

    one quick question about the variable node extrinsic mutual information (VNEMI) please.

    1. we can calculate the VNEMI using the ten Brinks formula, i.e.,
    I_ev = J(sqrt[(dv - 1)*sigma_A^2 + sigma_Ch^2]),
    where
    sigma_Ch^2 = 4/sigma_n^2 and
    sigma_n^2 = 1/(2*log2(M)*(Es/No)) (noise variance, Es=symbol energy)

    2. My question is that if we implement QPSK and 4-PAM, what will be the difference in sigma_n^2?. We know that the MI of both QPSK and 4-PAM are different. Please comment

  337. Mcrave20 Says:

    Dear Rob,

    I am facing the same problem with Sam and trying to demodulate BPSK after Rayleigh channel, I dont understand why it cant just be demodulated as normal e.g (rx+1)/2, where rx are the received values after transmitting through the Rayleigh and AWGN channel. I hope to gain better understanding in this. Just like you Sam, all works well in AWGN. I hope Rob could shed some light on this matter. Thanks :D I think this is a great site!

  338. Rob Says:

    Hello Ideal,

    In this case, you need to use…
    I_ev = J(sqrt[(dv - 1)*sigma_A^2 + [J^-1(I_demod)]^2]),
    where I_demod is the mutual information of the LLRs provided by the demodulator.

    Take care, Rob.

  339. Rob Says:

    Hello Mcrave,

    The simple answer is that because the channel is different, the received signal will be different and so the demodulator needs to be different. A more involved answer is to say that the demodulator needs to use h, in order to undo the phase rotation and fading that is imposed by the Rayleigh channel.

    Take care, Rob.

  340. Ideal Says:

    Dear Rob,

    Yes I do need to use, I_ev = J(sqrt[(dv - 1)*sigma_A^2 + [J^-1(I_demod)]^2]),

    but still I_demod is the function of sig_Ch^2 and the a-priori values. So I am asking what will be the formula for sig_Ch^ in the case of gray maping QPSK and real 4-PAM modulation schemes.

    I think in case of QPSK, we can use sig_Ch^2 = 4/sigma_n^2 = 8 * SNR but for the case of 4-PAM, what is this relationship? thanks

  341. Mcrave20 Says:

    Thanks Rob!

    That clears up my concepts a little :) so in other words if the transmitted BPSK signal is corrupted by a Rayleigh and AWGN channel, at the receiver, the first step to perform is equalization with rx_hat=rx./h then turbo decoding right? Also would just want to confirm that in practice, the channel coefficient estimated could be erroneous as it is an estimation right?

    Thanks so much Rob :)

  342. Rob Says:

    Hi Ideal,

    As far as I am aware, there is no closed form equation that links I_demod to sig_Ch^2 in the general case. I think that the only thing you can do is simulate the demodulator and measure I_demod.

    Take care, Rob.

  343. Rob Says:

    Hi Mcrave,

    That’s right. In practical scenarios, h would be obtained at the receiver using channel estimation. However, this can never be perfect and so a corrupted version of h must be used in practice. This will degrade the performance. In theoretical work however, it is typically acceptable to assume that perfect channel estimation is possible.

    Take care, Rob.

  344. Mcrave20 Says:

    Thanks Rob. That’s very helpful. Another quick question, what is the difference of equalizing a_rx/h then taking the real part of the result as compared to what you have done for the demodulator with:

    a_c = (abs(a_rx+h).^2-abs(a_rx-h).^2)/N0;

    I would be very much thankful if you could point me in the right direction on this. :)

  345. Rob Says:

    Hi Mcrave,

    If you divide a_rx by h, then you are not only amplifying the signal part of a_rx, but also amplifying the noise part. So, you would need to use a different value for N0 (although I can’t remember what value you should use)…

    Take care, Rob.

  346. Mcrave20 Says:

    Hi Rob,

    I see.. I think I have a better idea now. What a_rx/h does is zero forcing. I think that the codes provided might be implementing MMSE which takes into account of the noise power. I hope I’m not wrong, but I think the N0 is the noise power. N0=2/sigma^2. Thanks for the guide. Much appreciated!

    Thanks again for your help. :)

  347. Rob Says:

    Hi Mcrave,

    You are welcome.

    Take care, Rob.

  348. Mcrave20 Says:

    Hello Rob,

    I’ve just finished my number crunching for a Rayleigh channel with perfect channel knowledge with parameters below:

    16 state CCSDS Turbo decoder
    Modulation scheme:BPSK
    No_of_FRAMES=2810;
    INTERLEAVER_SIZE=1780;
    ITER=5; %Number of iterations
    RATE=1/2;

    with different Rayleigh coefficient for each frame and have also changed the demodulator to a_c = (abs(a_rx+h).^2-abs(a_rx-h).^2)/N0; To take account of the Rayleigh channel. The results does not seem right however, it performs much poorly than expected. At 10db, a BER of 10^-2 was obtained. Which does not agree with other reported works. Any ideas what could have gone wrong? again, it all works fine in AWGN.

  349. Rob Says:

    Hi Mcrave,

    It sounds like you are using a quasi-static Rayleigh fading channel - i.e. you use only one value of h for every BPSK transmission in the frame. This will cause some frames to have low BERs, but other frames to have very high BERs, which complete eclipse the frames with low BERs - even when the SNR is 10 dB. My advice would be to try using an uncorrelated Rayleigh fading channel - i.e. you should use a different value of h for each BPSK transmission in a frame.

    Take care, Rob.

  350. Mcrave20 Says:

    Dear Rob,

    That makes sense, I did implement a sort of controlled seed of h values for each frame, but it is a different seed (i.e. different h for each frame). I think I’ll re-run the simulation again and let the randn function run loose without control. Fingers crossed! Thanks again Rob :) You’ve been a great help :)

  351. Mcrave20 Says:

    Hi Rob,

    Turns out that I didnt transfer correct noise sigma values for AWGN.
    h*bpsk_tx + 10^(-ebnodb/20)*n;
    Did the trick. Also, I made sure to have different h for every frame. :) Just wanted to thank you for your advise and contributing to a working simulation :D Have a good day!

  352. Rob Says:

    No problem! Take care, Rob.

  353. Mcrave20 Says:

    Hi Rob,

    Hope all is going well. I just wanted to check whether my understanding is right on something. According to my simulation, for slow fading channels, i.e, the same h for each symbol in the frame yet different for each frame, the BER for turbo decoding is worse than a fast fading channel (different h for each symbols in the frame). After rechecking everything, I’m quite sure the problem earlier (with bad BER at high SNR~10dB) was because of this. Or that simply I would need to do a whole lot of simulation to obtain the correct BER result. From what I have observed, a channel with magnitude of ~0.1 has a very bad effect on BER and this seems to be the reason why I have been obtaining unexpectedly high BERs for high SNR. However, from the papers that I have been looking at, my result for fast fading channel seems to match the results reported in papers etc. When do I use fast fading or slow fading channels? Which do I stick to for publishing purposes? Thanks in advance for your advice :)

  354. Mcrave20 Says:

    Hi Rob,

    Another thought, maybe its better if I plot the Frame error rate instead of BER? Thanks.

  355. Rob Says:

    Hi Mcrave,

    In general, I would recommend fast fading channels for physical layer work and slow fading channels for network layer work. This is because these are typically the simplest channels that sufficiently challenge these types of work. Of course, you may prefer to use more sophisticated channel models if this is your particular focus. For physical layer work, I typically use BER, because this more easily shows how the frame length affects the performance of an iterative decoding scheme. For network layer work, I recommend FER.

    Take care, Rob.

  356. Mcrave20 Says:

    Hi Rob,

    Thanks again for your advice :) Much appreciated!

  357. Luke Says:

    Hi Robert. Is it possible to generate bits (e.g 1000000 bits) instead frame (40 to 5114) in yours matlabturbo ?

  358. Rob Says:

    Hi Luke,

    It is possible to use any interleaver length, although the UMTS and LTE interleavers only support a limited range of lengths. You can instead use a random interleaver by setting random_interleaver=1. This will allow any interleaver length, such as 1000000 bits.

    Take care, Rob.

  359. Elnaz Says:

    Hi Rob,

    I’m using BCJR-based turbo equalizer in my application and I have cross interference between different adjacent streams of BPSK message bits. In the receiver I somehow compensate for this interference but there is a weird behavior I see in my final BER curve. My BER curve is not always monolitically decreasing with increasing number of iterations and also with respect to increasing SNR values. I’m using sum reliability as my stopping criteria. However, if I use the error rate as my stopping criteria (i.e. if I cheat) to terminate iterations I do get monolitically decreasing curves. What do you think is the best terminating criteria to use here?
    Let me also add that I think this is related to the high amount of interference I’m dealing with; and, for now, I should stick to my not-so-strong interference cancellation method and try to get smoother BER curves.

  360. Rob Says:

    Hi Elnaz,

    If successive iterations are not improving the BER, then it sounds to me like your equalizer (or some other part of your receiver) is not working properly. My advice would be to see if this is the case by comparing the EXIT curves of the equalizer using both the averaging and histogram methods of measuring the MI. If the curves obtained using these two methods are significantly different, then it suggests that your equalizer is not working properly…

    Take care, Rob.

  361. Elnaz Says:

    Hi Rob,

    I have a question regarding the “eoor floor” problem. In order to get rid of this problem and have a nice, continuous falling down curve, do I increase the length of the stream or the number of averaging trials? Which one is more effective?

    Thanks,
    Elnaz

  362. Rob Says:

    Hi Elnaz,

    Increasing the number of trials in your simulation will not change the error floor - it will just give you a smoother and more accurate BER plot. Increasing the frame length will reduce the error floor. Another way of reducing the error floor is to use a better interleaver design - a good starting place is replacing a random interleaver with an S-random interleaver…

    Take care, Rob.

  363. Mcrave20 Says:

    Hi Rob,

    I’m trying to study the effects of SNR mismatch on turbo codes. In all literatures, the lowest BER will happen when there is perfect knowledge of
    the SNR, i.e SNR offset=0. I find that my simulation fits the overall profile but the problem is that the lowest BER point is at offset -6dB. I think one of the reasons for this is probably the way I calculated the values for sigma etc. Here is a snippet of my program, hope you could point
    me in the right direction

    %% SNR is fixed
    ebnodb=2;
    ebno=10^(ebnodb/10);
    N0=1/ebno;
    sigma=sqrt(N0);

    %% SNR Offsets
    START=-8;
    INTERVAL=1;
    STOP=8;

    for OFFSET=START:INTERVAL:STOP
    ebno_off=10^((ebnodb+OFFSET)/10);
    L_c_off=4*ebno_off;

    %% Fast fading channel (COMPLEX)
    h_u1=(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN))/sqrt(2); %ENC_OP_LEN is the length of the systematic bits u1, from RSC1.
    h_u2=(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN))/sqrt(2);
    h_v1=(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN))/sqrt(2);
    h_v2=(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN))/sqrt(2);

    %% AWGN noise (COMPLEX)
    n_u1=sigma/sqrt(2)*(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN));
    n_u2=sigma/sqrt(2)*(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN));
    n_v1=sigma/sqrt(2)*(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN));
    n_v2=sigma/sqrt(2)*(randn(1,ENC_OP_LEN)+1i*randn(1,ENC_OP_LEN));

    %% Apply channel effect
    rx_sig_u1= h_u1.*bpsk_tx_u1 + n_u1; % bpsk_tx are bpsk modulated bits
    rx_sig_u2= h_u2.*bpsk_tx_u2 + n_u2;
    rx_sig_v1= h_v1.*bpsk_tx_v1 + n_v1;
    rx_sig_v2= h_v2.*bpsk_tx_v2 + n_v2;

    %% Fix phase rotation and fading from channel with equalization
    u1rx = real(rx_sig_u1.*conj(ho_u1));
    u2rx = real(rx_sig_u2.*conj(ho_u2));
    v1rx = real(rx_sig_v1.*conj(ho_v1));
    v2rx = real(rx_sig_v2.*conj(ho_v2));

    Then it goes on to perform turbo decoding. Would appreciate very much if you have any advice. Thanks!

  364. Rob Says:

    Hi Mcrave,

    I suspect that the mistake is in the lines that come after what you have provided. Your equaliser makes the signal appear to have been transmitted over an AWGN channel, rather than a Rayleigh fading channel. However, the equaliser will change the SNR - I guess that you are just using ebno_off.

    My advice would be to use code of the sort…

    tx = -2*(bits-0.5);

    h = sqrt(1/2)*(randn(size(tx))+i*randn(size(tx)));
    n = sqrt(N0/2)*(randn(size(tx))+i*randn(size(tx)));
    rx = h.*tx + n;

    llrs = (abs(rx+h).^2-abs(rx-h).^2)/estimated_N0;

    Take care, Rob.

  365. Elnaz Says:

    Hi Rob,

    I am using the your BCJR algo as my equalizer in my application and the problem is that I see a “dip” in my BER curve in low SNR values.
    I have tested one thing: when using the exact Jacobian logarithm in the code I have the “dip” in low SNRs but when I replace it with the approximation of mode=2 the problem is resolved and the curve is linear, slightly higher error at low SNRs but linearly decreasing with increasing SNR.
    Do you know of any justification why this is happening? I mean why the exact definition gives me nonstandard behavior at low SNRs but the approximation doesn’t?

    Thanks,
    Elnaz

  366. Rob Says:

    Hi Elnaz,

    I’m afraid that I’ve never come across anything like that before. The only thing that springs to mind is perhaps one part of your system is assuming LLR=ln(P0/P1), while another part is assuming LLR=ln(P1/P0). I’m afraid that some of the code on my website assumes the former, while some of my code assumes the latter…

    To track the bug down, you could try my usual recommendation, which is to plot the EXIT curve for each of your system components using both the averaging and histogram methods. If these don’t match for a particular one of your system components, then that’s where I think you’ll find the bug…

    Take care, Rob.

  367. Mcrave Says:

    Hi Rob,

    Much thanks for your advice earlier. I did as advised but the results are not as expected. All of the mismatch results in 0 errors, only a severely underestimated channel with -8dB showed a slight error. There are a few things that I would need advice on.

    1) the estimated_N0 in this line should be from ebno_off from my earlier post right? i.e estimated_N0= ebno_off=10^((ebnodb+OFFSET)/10); then this is applied to
    llrs = (abs(rx+h).^2-abs(rx-h).^2)/estimated_N0;

    2) I also read from a few sources now that Lc=4*a*Eb/No*R, where R=rate, and a=fading attenuation (a=1 when channel is gaussian I wonder if I need to change for Rayleigh, if so to what value?)

    Again hoping you could point me in the right direction. It’s Chinese New Year from where I am, Happy Chinese New Year to all! :)

  368. Mcrave Says:

    Hi Rob,

    I found something that might be useful in point 2). “In case of no fading a = 1. In the case of fading with no channel state information the fading value becomes the expected value a = E[a] of the underlying fading channel. When we have ideal channel state information available at the decoder then a takes the exact fading value.”

    I am assuming a non CSI system. So a =E[h], for the codes suggested,
    h = sqrt(1/2)*(randn(size(tx))+i*randn(size(tx)));
    a=sqrt(1/2)?

    Thanks.

  369. Mcrave Says:

    Think I might be wrong. Rayleigh channels are zero mean. Hmm…

  370. Rob Says:

    Hi Mcrave,

    What you are saying in point 1 looks correct to me.

    With regard to point 2, the equation that I provided…
    llrs = (abs(rx+h).^2-abs(rx-h).^2)/estimated_N0
    …can be rearranged into the form…
    llrs=4*real(rx*conj(h))/estimated_N0
    I think that this is what you are talking about in point 2. Hopefully, my version of this equation shows you how to use it - although I don’t think that it will change your results…

    Take care, Rob.

  371. Mcrave Says:

    Dear Rob,

    Many thanks for your reply. I was able to get the expected results only when I apply

    h = randn(size(t));
    n = sqrt(N0)*(randn(size(tx));
    rx = h.*tx + n;
    rx = real(rx.*conj(h))/N0_off

    Not sure why though. It is probably because of its modulation type BPSK and most papers focuses on the real part of the symbol sent? Most papers I see so far are all on BPSK.

  372. Rob Says:

    Hi Mcrave,

    In this code, you are using only real noise and fading - there is no imaginary component to your results. This makes things more difficult for your scheme because all of the noise and fading is in the same dimension as your BPSK modulation, namely the real part of the complex numbers. In my version, the noise and fading is shared between the real and imaginary parts, making things easier for the BPSK modulation, since it is immune to imaginary noise and fading. I guess that the results you are trying to reproduce are using only real-valued noise and fading, in which case I think you have got everything correct. However, it is normal practice to use complex-valued noise and fading…

    Take care, Rob.

  373. Mahesh Says:

    Hi Rob,
    I have a very basic question regarding BER performance. When no coding is applied we get the Uncoded BER. Then we use FEC code to bring down the BER.
    Matlab 2012 has Turbo encoder- decoder demo (rate ~1/5.07). In this demo when I use BPSK (Bipolar) scheme, add AWGN noise and perform hard decision on received signal I got uncoded BER around 0.22; and Turbo codes were still giving coded BER ~10^-5. Is it possible?
    Is there any coding technique (with code rate < 1/6) available to handle uncoded BER of 0.22??????
    How much uncoded BER can be handled using present coding techniques?????

    Thanks

  374. Rob Says:

    Hello Mahesh,

    Your results do not sound unreasonable to me. Turbo codes can have very steep BER curves, allowing low BERs to be achieved at relatively low SNRs. By contrast, in the absence of coding, the BER plot will have a very gradual gradient, requiring a high SNR in order to achieve a low BER. Turbo codes having long interleavers are near-perfect codes - they can achieve very low BERs when transmitting data at a rate (in bit/s) which approaches the capacity of the channel.

    Take care, Rob.

  375. Mahesh Says:

    Hi Rob,
    When we say that the Ultimate Shannon limit is -1.59 dB, it means that no matter what code rate we use, we cannot perform reliable communication below -1.59 dB. Now for BPSK scheme, over AWGN channel, the uncoded BER at -1.59 dB is ~0.12. Means on an average 12% of bits (hard decoded) are in error. If turbo code can handle 0.22 uncoded BER isn’t that sound spooky. Because even in CCSDS 2012 report the turbo code with code rate 1/6 can go upto -0.2 dB Eb/No only. Which means it can handle only ~0.095 uncoded BER.
    I am working on a channel coding technique. What should be my AWGN channel model ? I have used BPSK scheme with Bipolar (bit 0 is modulated using +1 and bit 1 is modulated with -1) scheme. Then I add AWGN using inbuilt matlab “awgn” function and set the SNR to 3 (SNR=3 so for BPSK scheme Eb/No=0 dB). I do hard decision at the receiving end and I got the uncoded BER ~0.0786, which matches with the theory.
    I thought, channel coding is all about the amount of uncoded BER you can handle and everything in-between is just the process to achieve this goal.
    Please correct me if there is anything wrong with my understanding:
    i.e. Uncoded BER at -1 dB for BPSK is ~ 0.10
    When we encode 100 bits with code rate 1/6 we get 600 coded bits.
    When these 600 bits are transmitted at -1 dB Eb/No (or equivalent SNR) the received 600 bits will have ~0.10 * 600 bits in error
    We need to correct these errors and bring down the BER to < 10^-5

    I really appreciate your help.

    Regards,
    Mahesh Patel

  376. Rob Says:

    Hi Mahesh,

    I suspect that you may be getting confused between SNR and Eb/N0. The relationship between these is…
    Eb/N0 [in dB] = SNR [in dB] - 10*log10(eta),
    where eta is the number of bits of information that are conveyed in each transmitted symbol. In uncoded BPSK, eta is 1, so Eb/N0 = SNR.

    Take care, Rob.

  377. Deep Says:

    Hi Rob,

    I have implemented my own Turbo Encoder and Interleaver. Now I want to use your decoder. But I am completely stuck in the receiver side programs. Your decoder takes LLR inputs and LLR generation program needs mutual information while the mutual information program needs LLR inputs.

    So kindly will you please guide me from where will I start??

    One more question, the component_decoder.m is one constituent decoder. So to implement the complete turbo decoder just feeding the output of one decoder to another will work? Or I not to make other modifications?

    Waiting for your kind reply. Thanks in advance.

  378. Rob Says:

    Hi Deep,

    The functions for generating LLRs and measuring mutual information are only useful for drawing EXIT charts, to characterise the operation of the turbo decoder. These functions are not a part of the turbo decoder itself. Instead, your LLRs should be output by your demodulator. If you look in my main_ber.m script, you can see how I get a BPSK demodulator to provide LLRs to my turbo decoder. This script will also show you how to feed the LLRs produced by one component decoder into the other.

    Take care, Rob.

  379. Deep Says:

    Hi Rob,

    Thanks a lot. I am unable to understand the code in two different places.

    1. a_c = (abs(a_rx+1).^2-abs(a_rx-1).^2)/N0;

    Is this the LLR output of the BPSK demodulator? If yes, then how is it in the LLR form? Is it in normal domain or logarithmic domain? Will you kindly please explain a bit.

    2. errors = sum((a_p < 0) ~= a);

    You have used this line to make a hard decision and count the number of errors. My question is how we will make the hard decision. This line will just calculate the number of errors.

    Waiting for your kind reply. Thanks in advance.

  380. Rob Says:

    Hi Deep,

    1. This is the LLR output of the BPSK demodulator. It is in the LLR form - namely ln(P0/P1).

    2. The hard decision is obtained by

    decoded_bits = a_p < 0;

    Take care, Rob.

  381. Deep Says:

    Thanks Rob,

    One more question, if I want to use my LLR as ln(P1/P0) then will the changing of the modulator and demodulator be sufficient? Or I have to make changes in the decoder? Will the alpha,beta,gamma,delta calculation be the same??

  382. Deep Says:

    Dear Rob,

    Will you please explain a bit elaborately how
    a_c = (abs(a_rx+1).^2-abs(a_rx-1).^2)/N0;
    is in the ln(P0/P1) form?

  383. Rob Says:

    Hi Deep,

    You will need to make changes in the decoder. You need to change
    if transitions(transition_index, 3)==0
    if transitions(transition_index, 4)==0
    extrinsic_uncoded_llrs(bit_index) = prob0-prob1;
    to
    if transitions(transition_index, 3)==1
    if transitions(transition_index, 4)==1
    extrinsic_uncoded_llrs(bit_index) = prob1-prob0;

    Note that the equation
    a_c = (abs(a_rx+1).^2-abs(a_rx-1).^2)/N0;
    gives an identical result to
    a_c = 4*real(a_rx)/N0;
    Perhaps you are more familiar with this version of the equation…

    Take care, Rob.

  384. Selin Says:

    Hi Rob,

    Thanks for the code. My question is why you use the rate 1/2 for SNR calculations in main_ber.m. To quote your comment, you said \"Only the information that is used by the upper decoder is transmitted in this simulation.\" but it seems like you use the parity bits from both encoders in main_ber.m as far as I understand. Then, the rate would be 1/3 as in standard UMTS turbo code. Could you please clarify this?

  385. Elnaz Says:

    Dear Rob,

    I need to find the best LDPC code (parity check matrix) for my application. My block length =10 Kbits and rate=1/2 are fixed. Should I use PEG algorithm? Can you guide me to some codes for calculating the parity check matrix? I want to use the H with MATLAB’s LDPC encoder/decoder.
    I tested the code you uploaded above but it takes a long time considering 10 Kbits block length. When I feed the resulted H to fec.ldpcenc I get the error : “the last (n-k) columns of the parity-check matrix must be invertible in gf(2).” Can you please explain why?

    Thank you,
    Elnaz

  386. Selin Says:

    Hi Rob,

    I would like to also know if this code is punctured to get rate 1/2, how should I modify the script to simulate the turbo code with original rate 1/3?

    FYI, the reported UMTS BER vs Eb/No results on this website are significantly better than the ones I found here http://www.csee.wvu.edu/~mvalenti/documents/DOWLA-CH12.pdf and couple of other papers like this one: http://delivery.acm.org/10.1145/1340000/1330710/a105-iliev.pdf?ip=128.54.22.219&acc=ACTIVE%20SERVICE&key=C2716FEBFA981EF147DAD23CB8BFD2078D75470BC0F2371B&CFID=214026711&CFTOKEN=31039678&__acm__=1367864840_44a3b8b785b00ea67003e472fe6321ca.

    Thanks in advance,

    Selin

  387. Rob Says:

    Hi Selin,

    This is a rate-1/3 code, as you suspect. Please can you let me know where I say that it is a rate-1/2 code, so that I can fix it!

    You can increase the rate to 1/2 by discarding some bits before passing them to the modulator - you can either discard a random selection of bits, or use a particular puncturing pattern. In the receiver, the discarded bits should be replaced, using zero-values LLRs.

    Take care, Rob.

  388. Rob Says:

    Hi Elnaz,

    I’m afraid that I don’t know where to get a good algorithm for designing LDPC codes - in the past, I have always focused on the LDPC designs used in the standards. I think that Matlab’s decoder generates this error because it can’t work out the generator matrix from the parity check matrix you have provided it with - I’m afraid that I don’t know how you can fix this…

    Take care, Rob.

  389. Selin Says:

    Hi Rob,

    Thanks for the reply. In main_ber.m file, you use this equation to calculate noise variance
    % Convert from SNR (in dB) to noise power spectral density.
    N0 = 1/(10^(SNR/10));
    but σ^2 = 1/(2R *Eb/N0) and R = 1/3 in this case. So I think you are using a wrong variance value for your AWGN channel.

    Do you happen to know about the MATLAB\’s new built-in Turbo Encoder and Decoder? I get worse performance in terms of BER with MATLAB\’s own implementation of this and wondered if you have any knowledge of this.

    Thanks,

    Selin

  390. Rob Says:

    Hi Selin,

    I agree that σ^2 = 1/(2R *Eb/N0) in the case of BPSK modulation. However, I don’t agree that this is inconsistent with N0 = 1/(10^(SNR/10)). I think that both equations are true.

    I guess that you are referring to…
    http://www.mathworks.co.uk/help/comm/ref/turboencoder.html
    http://www.mathworks.co.uk/help/comm/ref/turbodecoder.html
    I’m afraid that I don’t have the latest version of Matlab, so I haven’t been able to try these…

    Take care, Rob.

  391. Selin Says:

    Hi Rob,

    I guess if you are defining SNR as Es/No, which is R*Eb/No, then yes, both equations would be correct. ( σ^2 = N0/2 = 1/ (2 SNR)) => N0=1/(SNR) = 1/(10^(SNRdB/10)) )

    As for MATLAB\’s implementation, they provide the demo results for UMTS turbo code on this page http://www.mathworks.com/help/comm/examples/parallel-concatenated-convolutional-coding-turbo-codes.html#commpccc-13
    Link for the BER curve:
    http://www.mathworks.com/help/comm/examples/commpccc_03.png

    These results are clearly worse than those provided here:
    http://www.csee.wvu.edu/~mvalenti/documents/DOWLA-CH12.pdf

    Do you have an opinion or sources you can refer me to help me figure which one is correct?

    Thanks,

    Selin

  392. awatef Says:

    bsr,svp pouvez vous me donner les differrent code rate (pattern puncturing)des reseaux telephonie(LTE,UMTS,GPRS,CDMA2000,CDMA,HSDPA,HSUPA,HSP+…).j’ai besion de ces codes rates urgent et
    merci d’avance

  393. Rob Says:

    Hi Selin,

    That’s right - I’m using SNR as Es/N0.

    It looks like the Matlab turbo decoder provides sub-optimal performance for some reason. Both my results and the results in the book you have linked to are superior. If I were you, I would trust that book over Matlab…

    Take care, Rob.

  394. Rob Says:

    Hello Awatef,

    I’m afraid that I don’t have any code for these different puncturing patterns - I normally focus on unpunctured codes…

    Take care, Rob.

  395. Rob Says:

    Hello Awatef,

    I’m afraid that I don’t have any code for these different puncturing patterns - I normally focus on unpunctured codes…

    Take care, Rob.

  396. awatef Says:

    @ ROB
    je vous remercie tout d’abord pour votre reponse.E nsuite

    j’ai besion de connaitre les défferentes motifs de poiçonnage non les codes.c.a.d j’entrain de faire une recherche sur les les défferentes motifs de poiçonnage afin de les coder plus tard.
    merci

  397. Selin Says:

    Hi Rob,

    Thanks for taking the time to look at those graphs. I decided not to use MATLAB’s turbo decoder since all the other turbo code performances seem to be matching except for MATLAB’s. Did you publish any of your BER results in a paper so I can refer to them as well? (I’m a PhD student at UCSD and using turbo codes as part of my research)

    Awatef,
    You might want to have a look at the CML library. They have puncturing methods there. http://www.iterativesolutions.com/download.htm
    Also, for optimal puncturing patterns for certain constituent encoders (unfortunately not UMTS, but still gives you an idea), you can refer to this paper:
    http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=848555&tag=1

    Cheers,

    Selin

  398. awatef Says:

    un grand merci selin.
    mais les fichiers sont (.mat)en exel.ils ne s\’ouvrent plus.
    merci

  399. Rob Says:

    Hi Selin,

    We have published some LTE BER plots in…
    http://eprints.soton.ac.uk/271820/

    Thank you for offering some help to Awatef. Your French must be better than mine!

    Take care, Rob.

  400. Rob Says:

    Hi Awatef,

    I’m afraid that my French is rather rusty and so I’m not sure what you are asking for. I wonder if you can restate the question in English?

    Take care, Rob.

  401. awatef Says:

    a big thank you Selin.
    but the files that are in (CML Source Code) are files with extension (. Mat) (in Exel) so they s’ open more.
    thank you

  402. awatef Says:

    a big thank you rob

  403. Selin Says:

    Hi Rob,

    Thanks a lot. All the BER curves but Matlab’s are indeed matching.

    Awatef,

    If you download the cml.1.10.zip, you can see that under cml/mat folder, there are MATLAB files with .m extension. And depending on what you exactly want to simulate, you can just run the CmlSimulate.m with the already existing scenarios by only changing the puncturing pattern as you wish. .mat files are just outputs they simulated before and provided for convenience. Hope that was helpful.

    Selin

Leave a Reply

Security Code: