 Welcome to this lecture on digital communication using GNU radio. My name is Kumar Appaya and I belong to the department of electrical engineering IIT Bombay. In the previous lectures, we have seen an introduction to the concept of linear block codes. We have then also looked closely at repetition codes and their utility. In this lecture, we are going to use GNU radio in order to build a repetition code encoder and decoder. What we will see is that encoding for the repetition codes is very easy because we will use the repeat block in GNU radio merely to repeat the bits that many times. For decoding, we will perform majority logic decoding that is we will count the number of ones. The number of ones is more than n minus 1 upon 2 or so. We will conclude that it is a 1. If it is less, then we will conclude it is a 0. For this, we will implement our own python block where we count the number of ones and let us say for a 3 repetition code, there are 2 or more ones we will conclude it is a 1 and for a 0 or 1 ones we will conclude it is a 0. We will also use a histogram with noise to show that the repetition code is very robust even in the presence of errors. We will begin by first having an equivalent of the binary symmetric channel by using BPSK with additive white Gaussian noise as our channel. So let us begin. We will first have a random source so control for command F we will say random. We will place our random source over here as usual we will convert it to byte data type but we will keep the number maximum S2. We will add our constellation related blocks so I do control for command F we will say constellation. We will grab our constellation object and the constellation encoder the constellation object we will set to BPSK and give it the name my BPSK and the constellation encoder we will connect and then we will call it my BPSK so that it uses the object. We are now set we will add a throttle control for command F we will say throttle after the throttle is connected we are now ready to add noise so we will add a noise source but before that let us actually make this real because for BPSK we can do with a real channel. So control for command F we will say complex to real and we will have the complex to real and then add a noise source so control F command F we will say noise we will keep a noise source over here make the noise source as a float and make the amplitude as noise is TD so that we can control the amplitude and control F for command F we will say add and then this add block will convert to float and then of course the noise is TD needs to be arranged for for that we will use a range so control F for command F we will say range and we will double click the range make the name noise is TD the default value 0 will stop it around let's say 10 step 0.1 and we're set now we can there we can then just do a couple of things we can decode the constellation so control F for command F we'll first say float to complex so that we say float to complex over here okay now the float to complex the imaginary part needs to be 0 so we'll add a constant source control F for command F we'll say constant we'll grab a constant source we'll make the constant source of float type and value 0 connected yeah we can now grab the constellation decoder so control F for command F we'll say constellation decoder and once you have the constellation decoder you now have access to the bytes that is the bits as well we will double click this and make this my BPSK now we can compare the original data with the decoded data so for that we will use two approaches the first is we'll have a time sink so control F for command F we'll say time sink we will rotate the time sink using the left key double click we will make the type float and make it have two inputs and unfortunately these are bytes so you need to convert them so we'll have a character to float so or maybe we'll just rotate it right and keep it this way we'll have a character to float so control F for command F we'll say C H A R actually so there is a character to float we will gap that connect the original data source here connect it to the first input we'll come copy another one control C control V and rotate this connect this to the second input and now we can visualize and we have something like this the red and the blue are overlapping because there are no errors now noise is TD controls the error if you now increase the noise is TD you'll start seeing errors occurring and these errors are the points where the blue and the red do not match and it is very evident let's stop and you can see over here the red you know wherever the red and blue overlap it is good but for example at these spots the blue is here the red is here there is an error similarly over here the blue is here the red is here there is an error over here there is no error but there are errors now if you let this run you will see that if you increase the noise variance you'll start getting more and more errors and you will get a completely random effect you can also verify this using a histogram sync so let's just rotate this to the left and maybe I can just add a histogram sync over here let's say control F for command F I'll say histogram sync now for the histogram sync I'm going to actually subtract these two and if I subtract these two I will either get 1 minus 0 which is 1 1 minus 1 which is 0 or 0 minus 0 is 0 or 0 minus 1 which is minus 1 so I can subtract these two and take an absolute value if I get a 0 that indicates no error if I get a 1 I get an error so I'll just control for command F I'll say subtract and I'll make this a float I'll subtract the original stream from the decoded stream and I'll also add an absolute block control F for command F say a b s and we'll make this a float and now we will come pass this subtracted output through the float and now we have a histogram sync so if you execute this flow graph this blue indicates that let's just remove the auto scale y blue indicates that there are a thousand out of thousand decoded correctly if you increase the noise STD you will start getting a one over here indicating errors so over here you have about 400 like 400 errors and about 600 are being decoded correctly if you reduce the P that is the bit error probability then you get 300 incorrect about 600 700 correct so you have a knob within which you can control the errors you can see that a lower probability of error you decode correctly a higher probability of error you make mistakes and if you have an extreme probability of error then it's 50 50 you have bit error rate of half which means it's as good as a coin toss so in this manner we have essentially constructed a standard binary symmetric like channel our next task is to add a code in order to see that the performance actually improves let us do that to do this we are going to use a repetition code and the easiest way to realize the repetition code is to just repeat the transmitted bits and at the receiver as you discussed in class you can decode them and use majority logic to capture them so do controller for command if I'm going to say repeat and I will get the repeat block the repeat block I'll double click I'm going to say interpolation is three and the type is bite so now I can connect the random source over here and now the interpolation is three of course I could have taken the encoded output and repeat it as well but let me just add a constellation encoder again so I'll do control c control v have a constellation encoder I don't need a throttle because only one throttle is enough for one flow graph I'll grab a complex to real control c control v connect this over here now since this operates at a rate slightly different because I am interpolating by three I will grab a fresh noise source so control c control v this also uses the same noise std so I am set I'll add control c control v the ad block and connect these over here next I will get the float to complex because I need to convert it back so I'll actually kind of copy all these three objects by like this and do control c and control v and move these over here now I can connect this to make convert it to real and then this is the constellation decoder the decoded output can now be viewed in the qt gi time sink or the ut histogram sink but first I need to decode and get back the majority logic so I'm going from three to one to do that I'm going to split this output into three so I'm going to use controller for command f and say stream demux so the stream demux can be used to split every three outputs and give them to me in parallel so I will connect this over here of course I need to change the type I double click change this to byte change this to one one one or if you want to write it compactly star one one star three with three and now I need to perform majority decoding logic on this in order to perform majority decoding on this there are multiple ways the key idea is for you to say if there are zero or one ones then conclude that a zero was sent if you have two or three ones conclude that a one was sent this is something that we have seen explicitly in the class so but implementing the majority logic you can do it in multitude of ways we are going to use a python block so controller for command f we will say python and grab the python block we will double click this python block open an editor choose any editor that is convenient for you and now let us edit this to perform the majority decoding logic remember we need three character or byte inputs and one byte output so we are going to just get rid of these comments first now over here we don't need this comment we don't need this parameter now let us first call this majority decoder i'll call this np.int8 i need three inputs so i'll just say np.int8 three times and the output is a single np.int8 these np.int8s are either zero or one they are not they don't contain eight bits it's an eight bit vector containing only zero or one in the least significant bit that is the key thing that you have to understand so all we need to do is to find the number of ones and zeros in each of you know in these three parallel inputs and then conclude what was sent based on that now the work function in the work function we have to change this let us do it carefully the way we are going to implement our majority decision logic is to add up the inputs so if you add up the inputs each entry is going to be either zero or one so if you add up the three inputs you're going to get either zero one two or three so if you add up the input let's say temp is input item zero plus input items one plus input items two now in temp you have an array consisting of the array it's like the addition of the arrays input items zero one and two each of these has zeros and ones and the entries are now going to be zero one two or three now in temp which we're going to map to the output whenever you have two or three you want to set it to one whenever you have zero or one you want to set it to zero let's first handle the zero or one case first so temp wherever temp is zero or one we'll say temp less than or equal to one is zero wherever it is two or more we'll set it to one finally all we are going to do is to map this output items as temp and this is done now why does this work see input items is an array it's like input items zero input items one input items two are all arrays of the same length each corresponding entry has the three repeated code which has gone through your binary symmetric channel now our task is to conclude what was sent based on the most likely event the most likely is that a single error has occurred or no errors have occurred if a single error has occurred then you will either get if you send zero zero zero zero zero zero zero one zero one zero or one zero zero that means if there is a single one you can just conclude zero zero zero was sent if there are two or more ones one one one was sent and then you map back the correct bit so let's save this and exit and now we have a nice majority decoder we can connect these up and this majority decoder output can then be compared let's first do the time comparison so we'll add three inputs go down every input is three and now we can copy this character to float control c control v grab this over here connect this up connect this up and now if you execute the flow graph you see a green also that matches the blue no errors and if you increase the noise then you will see that the green let's say that we set it here you will see that the green essentially will track the blue more often so if you look at the green and blue versus red and blue red will have more errors let's set the error to be a little lower and you'll basically see let's say we set it here you will see that the green and blue have few errors there are very few spots where there is a mismatch but if you look at the red there are many more spots where there is a mismatch of course the true way to find this is to view the histogram so let's modify the histogram so I'm going to double click let's not auto scale and let's add two inputs now the second input you have to perform the same operation you have to perform a subtraction and absolute with the original let us actually do that so I'm just going to copy control c control v I have the subtraction over here connect this output to this over here and connect the original over here and again an absolute so control c control v I'll grab an absolute I'll grab move this absolute over here connect this and connect it to the output let's just move this to the right a little so that you can see what is happening now if I execute this flow graph you can see that there's a red and there's a blue which are overlapping in fact maybe let's actually do one thing let's swap these so that you know the second one essentially or let's just leave let's just let's just swap these yeah now if you execute the flow graph yeah it doesn't matter maybe I just undo that yeah if you now increase the noise you will see that the blue one pops up when the red one pops up the red one is with the repetition coding as you can see the number of errors is much higher in the case of the blue one which is without coding while the red one is pretty robust because of the fact that you are performing repetition coding let's increase the noise as you increase the noise you are able to see that the both the peaks fall but again the red one is below because repetition coding allows you to correct the errors at least one error among three it is able to correct most of the time now as always if you increase the effect of repetition coding you are going to get better performance for example if you set this interpolation to five and if you set this to five and if you change the majority decoder to account for five errors let's do that so we need to add two inputs here we've added two inputs now let's add them here also now in this case when you have five we have to change this slightly zero one or two will result in zero three four or five will result in one let's now inspect our performance okay so let's I think I made a small error I'm sorry so if you now look over here in p.int8 in p.int8 yeah there was a small syntax error I apologize so we'll fix the syntax error there should be a comma here this will fix things now we can connect these over here and this particular code will result in even more of error correction okay let's see so he says list index out of range yes so there's one two three four five zero one two oh three four I'm so sorry yes now if you execute this flow graph you will see that even with a slightly more number of errors you can see that the red one is much better in fact if you see if you can compare with the same let's say 1.5 the noise standard deviation you will see that the red one is actually much lower because you're able to now correct two errors remember the five repetition code can correct two errors even with a higher amount of noise you can see that the number of error correct the amount of error correction offered by the five repetition code is very very significant let us go one step further and let's make this nine here also we'll make it nine and here we'll have to make it nine in order to avoid these kinds of errors let us actually just make this star nine that will give me nine inputs and over here you know you can always just do plus five six seven now in the case of nine zero one two three four will be the result you know if they're up to four ones you can conclude zero five or more ones you have to conclude one right so now let us evaluate the performance of this block connect these connect these connect these connect these and if you now execute your flow graph let's set it to the same 1.5 with 1.5 you can see that the errors with the coding is even lower in fact only about five percent of the bits are in error and rest are all correct even if you increase the noise the red one is very very robust and you are getting a much much more effective error correction because of the use of nine length repetition of course as you saw repetition coding results in very good performance but the price you pay is you have to essentially reduce the rate to one ninth and that is a major price that you have to pay and therefore repetition codes may or may not be very useful in the longer kind of in all kinds of systems where efficiency is needed which is why we will move on to better codes like hamming codes in the next lecture. One final remark in particular I want you to just note a trick when you use the histogram sync is that one issue with the current implementation is that this blue and red are overlapping and it's sometimes difficult to see you know how much height there is and everything like that of each separately you have to hide one over the other so since the values are zero and one we can play a trick by offsetting one of these to a small extent that is let's say you can add a constant to one of these so let me do this so controller for command f I'll say add constant and I'll add a floating constant of let's say minus 0.2 if I add the constant minus 0.2 before sending it to the histogram you can see the histogram bins separately so if I hit run so you can see them separately so now if I add noise also you can compare the heights of these more conveniently on the same graph so it's very very convenient and you can sort of visualize things in a much easier way the other remark that I wish to make is that if you have an extreme amount of noise in this case if I make the noise standard deviation 10 that corresponds to noise variance of 100 so it's like the snr is close to 1 upon 100 then you can see that the performance is essentially really poor for both of these of course still the repetition code's height is better because it is able to correct some amount of errors but this confirms our hypothesis that as the p goes to half that is your eb by n naught goes to zero as you discussed in class the error performance becomes poor even if you have coding if the error is a noise is too much you cannot recover the performance this is something that you have to remember in terms of the bpsk the n naught is very high so you can't really distinguish between the plus 1 and minus 1 very easily in this lecture we have built a repetition code based error correction system in GNU radio as we saw the error repetition based error correction code also encountered errors but it is much much more robust than the uncoded system and we saw that even when you have a large amount of noise the repetition code resulted in a significant amount of error correction and performed much better than the uncoded system as we saw by looking at the histograms comparing the correct and the erroneous bits decoded one major issue with the repetition code however is the fact that it is very poor in terms of rate because you are essentially repeating for nine repetition code you are repeating it nine times so when compared to the uncoded case your rate is one ninth there is a huge amount of overhead or loss in performance in the next lecture we will look at the hamming code which is very effective at correcting a single bit error and it's it still offers a much higher rate than just a plain repetition code thank you