Line Codes - Matlab / GNU Octave Code
Published by Arun Isaac on
Tags: signals, matlab, octave, software
Our lab work was to implement various line codes in a Matlab script. The expected approach was to input the digital data, chuck it into a for loop and thus generate an appropriately line coded square wave. First of all, I thought the whole exercise was pointless, and second, I don't quite like writing for loops in Matlab.
So, after some thought, I came up with the following approach to do line coding without for loops. My approach involves a bit of system theory, modulo 2 arithmetic, and sometimes just tricks founded on simple coincidence. So one is advised to be a little careful while sifting through the logic. But ultimately, the code is terse and fairly elegant.
Each function (unipolar, bipolarnrz, bipolarrz, ami, manchester, diffmanc) generates a list of symbols (1 corresponding to +5 volts, 0 corresponding to 0 volts, and -1 corresponding to -5 volts), and call the function 'maptowave' to convert the list of symbols to a modulated square wave with the appropriate voltages.
function wave = unipolar(data) wave = maptowave(data);
Unipolar encoding is simple. The digital data itself can be directly mapped onto a square wave.
function wave = bipolarnrz(data) data(data == 0) = -1; wave = maptowave(data);
In bipolar (NRZ) encoding, the '0's are represented by negative voltage levels. So, all '0's in the data are converted to '-1' and then mapped onto a square wave.
function wave = bipolarrz(data) data(data == 0) = -1; data = upsample(data, 2); wave = maptowave(data);
Bipolar RZ coding operates at twice the frequency of bipolar NRZ coding, returning to a zero voltage level every half cycle. Hence, upsampling is needed to create the return to zero effect.
function wave = ami(data) am = mod(1:length(data(data == 1)), 2); am(am == 0) = -1; data(data == 1) = am; wave = maptowave(data);
In AMI (alternate mark inversion), '1's are called marks, and '0's are called spaces. Marks are represented by alternate positive and negative voltage levels. The code shown above first generates alternate marks (1, -1, 1, -1,…) in the variable 'am' and then replaces all the '1's in the data with these alternate marks.
function wave = manchester(data) data(data == 0) = -1; data = upsample(data, 2); data = filter([-1 1], 1, data); wave = maptowave(data);
In Manchester coding, '1's are marked by an upward transition, and 0s are marked by a downward transition. Upsampling is required since the code operates at twice the frequency, the transitions happening in the middle of each cycle. The code shown above produces upward/downward transitions by replacing the '0's in the data with '-1' and then convolving with an impulse response [-1 1].
function wave = diffmanc(data) data = filter(1, [1 1], data); data = mod(data, 2); wave = manchester(data);
In Differential Manchester coding, output feedback is involved. The present output not only depends on the present input but also on the previous output. If the present input is '1', the present output will be the reverse of the previous output. If the present input is '0', the present output will be the same as the previous output.
So, for example, if the previous output was an upward transition, and if the present input is a '1', the present output will be a downward transition. Or instead, if the present input is a '0', the present output will be the same upward transition. In the code shown above, a suitable modulo 2 filter is used to translate the data to a form which when Manchester coded will produce the same waveform as when the original data is Differential Manchester coded.
function wave = maptowave(data) data = upsample(data, 100); wave = filter(5 * ones(1, 100), 1, data);
The function 'maptowave' as mentioned earlier, maps a list of symbols (1, 0, and -1) to voltages (+5, 0, and -5) respectively.
For a more detailed treatment of line codes, please refer Line code in Wikipedia.