 We have said in the topic on data transmission impairments in our communication system mean that what we receive is not the same as what is transmitted. We have noise and attenuation and one of the results of those impairments is that the data received is different from what the data was transmitted. With digital data we measure that as bit errors. I transmit the bits 1100 and I receive 1110, we have a one bit error. So that's a problem. That's ineffective data communications. So here we're going to introduce some ways to deal with errors. And the two things we want to do with deal with errors is to first detect that there is an error and then fix it, correct the error. But just to illustrate the need for error detection, let's consider we have a transmitter. It transmits some bits, let's say it transmits a sequence of seven bits, it doesn't matter the length. And you're the receiver and this is the sequence you received, there's seven bits you received. You're the receiver, you receive those seven bits, is there an error or not? Look at the bits and tell me if there's an error in those bits or not, yes or no? You don't know, good answer. That's the problem. The receiver gets seven bits, how do you know if that's right or wrong? How do you know if that's what the transmitter actually sent? Well, we don't know. And that's the problem that we have to deal with. We know that maybe there is an error, maybe there's not. We would like to know for sure, is there an error in these seven bits or is it perfect? Is it what the transmitter sent? We can't just ask the transmitter, is it the same? Because that's the idea of receiving the bits, it's the data communication. So we need some other way for the receiver to check, is this correct or not? And that's what we call error detection. So there are different ways to deal with errors. So first, some classification of types of errors. If we talk about a frame being sent, we know a frame has header, payload and trailer, each containing a sequence of bits. The errors, we transmit a frame from transmitter to receiver. The receiver receives the payload and it has one or more bit errors. We can say that's a damaged frame. It's that we receive the frame, but inside it has some errors, we say it's damaged. Now the errors maybe in the payload, the header or trailer, we'd still call a damaged frame. So the transmitter sends me a thousand bit frame, I receive a thousand bits and we'll see later I somehow detect that some bits are in error and I would call that a damaged frame. We want to be able to deal with that. I receive a damaged frame. I want to be able to fix the damage to correct the errors. But another type of error we can talk about is that the transmitter sends a frame and I don't receive it. So this is a lost frame. This may happen in some cases where a frame or a sequence of bits is actually sent but nothing's received. Maybe there was significant interference or there was failure of the cable or a failure of one of the components such that during the transmission nothing's received. So we call this a lost frame. How can we deal with a lost frame? How would I know as a receiver that a frame has been sent to me when I didn't receive it? The transmitter knows it sent me a frame. I don't know that because I've received nothing. I'm just sitting here waiting. How can we deal with that? How would I detect that a frame has been sent to me but I didn't get it? A sequence number, that is, if the transmitter has, say, three frames to send to me and including the header of those frames, it includes a number, one, two, and three. And the transmitter sends frames one, two, and three to me. And here I receive frame one, good, then I receive frame three. Maybe that's an indicator to me that, all right, I expected to receive in sequence number, the frame should come in order. If I receive frame one and frame three but I don't receive frame two, maybe that's because frame two was lost. So that's one way to detect lost frames. And we'll see it comes up into something we'll mention as ARQ. The other thing is in types of errors, we transmit frames one, two, and three. I receive frames one, three, and two. I receive them out of order. Let's say that those three frames contain a file that was being transferred. It's in three parts. I put the file back together, but I put it back together in the wrong order then the file could be useless. That is, the file is a song and I put the end of the song in the middle position in the middle part of the song at the end when I play it back it's not the same song. Sometimes we care about getting the frames in order, most of the times. So if I receive them out of order, we can say that's an error. And sequence numbers help here as well. If I receive frame one, three, two, I can realize, let's swap three and two around and put them back into order. So there are two things that we want to do to deal with errors. We want to first detect to know that there are errors. And once we know that there are errors, we want to fix them. Error detection and error correction. And there are different approaches to dealing with error detection and correction. We will not cover all today. For error detection, one general approach is that when the transmitter sends the frame, it attaches some extra information such that when the receiver gets that extra information plus the data, it can apply some algorithm to calculate is the data correct or not. And we'll go through that today. There's a very simple way to do that. But we attach extra information to what we want to send such that that extra information is specially chosen so that the receiver can check if the data is correct or not. Parity check is what we'll go through today. In the following slides, I'll simply refer to that as an error detection scheme. There's other ways to detect errors. Like we said, how do we detect a lost frame? Include sequence numbers in the frame. So if we get one that's missing, we assume that's a lost frame. And those schemes of including sequence numbers, we'll talk about after the midterm in a topic and a techniques called automatic repeat and request, ARQ, that we'll not cover today. We find out there's an error. We want to fix it to general approaches. Error correction, forward error correction involves the transmitter, attaches some extra information or transforms the data that it wants to send such that when the receiver receives this transformed, this modified information, it applies some algorithm so that it can both detect that there was an error and fix the error. So we'll go through that today. We'll call it forward error correction. And we'll show a simple example of how the receiver can fix errors. And the other approach is, I think we've mentioned before, I detect an error, I tell you to send me again, retransmit. So these retransmission techniques and the use of sequence numbers fall into something called ARQ, but we'll cover that in the next topic, not today. So let's look at error detection schemes using just one simple example and another simple example of forward error correction to explain those concepts. Error detection, simple one I think you've heard of, you've used or seen in maybe some computer hardware topics. Parity check, use a parity bit on the data. Two different approaches, odd and even parity check. That's for this example, use odd parity check. I want to send some data to the destination, and I want the destination to be able to check if the data they get is correct. So what I do is I attach a parity bit to that data where the value of that bit, zero or one, follows some rules. And in an odd parity check, the rules are quite simple. The total number of ones in that sequence should be odd. And even parity check, they should be even. And the receiver, when they receive the data plus the parity bit, check, did I receive an odd number of ones? If so, good, nothing's gone wrong. If I receive an even number of ones, I know something's gone wrong because the transmitter only sends an odd number of ones. If you receive an even number, there must be a bit error somewhere. So let's illustrate that and show the capabilities of error detection schemes by I want to send my name to someone, first letter, uppercase S. Let's send that and use a parity, odd parity check on that. What's S in binary? We look up our ASCII table and we find uppercase S is the seven bits, one, zero, one, zero, zero, one, one. That's our data I want to send just for this example. If you want to send your name, you can find the characters here. But we just want those seven bits of data. So we're going to transmit the data from A to B and the data we said S was one, zero, one, zero, zero, one, one. And we're going to use odd parity check. As the transmitter, B is going to receive the data. And what we'll do is we'll consider several cases. What happens if there's some errors on our link? We'll transmit this data. What happens if something goes wrong on the link and see what B does to try and detect the errors? What is transmitted by A in this case? With odd parity check, we attach one more bit. We add some extra information. If we want to send the data, or the payload, one, zero, one, zero, zero, one, one, we attach a parity bit. What's the value of the parity bit? Hands up for left hand up for zero. Left hand up for zero. Right hand up for one. Odd parity check, the total number of ones should be odd. So we currently have four ones, an even number of ones. Adding another one gives us an odd number of ones. Where do we add the parity bit at the start or at the end? I don't care as long as both A and B know. Here in my example, I'll add it at the start. Think of it as the header. So we'll add a parity bit and then the seven bits of payload. Why is this a one here? So here's our parity. I've added it at the start. When I count bits in this course, I count from left to right. So this is the first bit, the second, and this is the eighth bit. In total, there are five ones, an odd number of ones. That's all. We must transmit an odd number of ones always. Any questions so far? This is just how we create what we transmit. Seven bits of payload, one bit of header in this case, or overhead. We send that and now let's consider different cases in terms of what B receives and under different error conditions. So what's the first case we can consider? It's always the same eight bits transmitted. Let's say the errors will consider what's received and then we'll see what happens. So in the first case, say the errors, there are no errors. We transmit these eight bits along the link. Nothing goes wrong. No errors. So what's received? Exactly the same as what's transmitted. So the eight bits received, this is a simple case. We don't need error detection here. There are no errors, but let's see what happens. Now the receiver with an odd parity check will count the number of ones. Check if it's odd. If it is, assume everything's OK. If it's even, assume something's gone wrong. Here we count the number of ones. There are five. OK. Everything's OK because we have our expected odd number of ones. We could remove the first parity bit and now we have our data correctly received. So what I'll say here is that the receiver, all right, the receiver in this case assumes that the data it's received is correct. I'll give it a tick. Meaning that eight bits I received match the rules of having odd number of ones. So I assume that nothing's gone wrong. I assume it's correct. I'll remove the first bit and here's my data. And that's the correct thing to happen in this case. So I'll say the outcome or the result of this error detection scheme was successful. The receiver assumed there were no errors. In fact, there were no errors. So the error detection scheme passed. It worked. We'll see some other cases where it may not work. Let's try a different case with some errors. We want to detect errors. Let's say the eighth bit is in error. Just one bit error, the eighth bit or the last bit in our sequence is in error. So what do we receive? Well, the first seven bits will be the same and this will be bit zero. We transmitted the eighth bit. It's one. If it's an error, it means it arrives at zero. The receiver goes through the rules of its error detection scheme. And the rules are count the number of ones. We have four ones. Is it odd? No, it's even. Something's gone wrong. Assume there's an error. That's all. If we don't get an odd number of ones, there's something must have gone wrong because we know according to the odd parity check, A will always transmit an odd number of ones. So if we get an even number, must guarantee that there was an error. Something went wrong. So when I say the assume here, it's the assumption made by the receiver based upon the error detection scheme. Was that assumption correct? The receiver assumed there were errors. Were there errors? Well, yes. One bit was an error. So we can say that the receiver made the right decision there in terms of detecting errors. So the result of this error detection scheme is it worked. Note that the receiver doesn't know where the error is. It just knows that there is an error. So this is not trying to correct or fix errors. It's just trying to identify, are there any errors in these eight bits? Whether it's the first bit, the second, or the eighth, we don't know at the receiver. We'll deal with that later. Let's consider some other cases. Let's say the first bit. The first bit is in error. So we transmit the same eight bits. The first bit is wrong, so we get this. What does the receiver assume happened? Even number of ones must be an error. I expect an odd number. I get an even. Assume there's an error. Did the receiver make the right assumption? Was there an error? Yes, there was. So we assumed correctly at the receiver. I say the outcome, is it? The error detection worked. Again, where is the error? I don't know. Remember, the receiver can't see this. You can, you know where the error is, and I told you here, but all the receiver gets is this. So realize that this is just error detection. It's not identifying where the error is and trying to fix it. Count the ones at the receiver, if odd, okay, if even, error. Another example, let's say the second bit and the fifth bit are in error. We transmit these eight bits. The first bit is okay. The second one is wrong. Actually, before we do this, I forgot to say the difference between the previous two, the eighth bit and the first bit. Just note that even though it's the parity bit in error, the receiver doesn't care. The receiver still detects an error. So with the eighth bit in error, it was one of the data bits, one of the payload bits wrong. I knew that, but the receiver didn't. In this case, with the first bit in error, it's the parity bit which is wrong. The data is still correct. 101, 0011, the original data is the same, but the parity bit is wrong here. That still is an error. We still treat that as an error. So when we detect the error, yes, there's an error, then that's the correct outcome here. Second and fifth bit. Second bit is wrong. Fifth bit is wrong. What do we assume? What happens at the receiver? How many ones? How many ones? Five ones? How many ones received? Odd or even? Odd, okay? We received this. So you're the receiver. Don't look at any of this. You can't know what was in error. You don't know what was transmitted. You just get these eight bits. You count the ones. Odd number of ones. What do you expect? You expect to get an odd number of ones. So you assume no error in this case. Because the rules say, if there's an odd number of ones, it's okay. If it's an even, there's an error. We got an odd. We assume what we got is correct. Was that the correct assumption? The receiver thinks what it got is, has no errors. But we know that there were errors. So the result of this error detection scheme is it failed. And this is the point to illustrate. Error detection schemes are not perfect. Here, there's a case where when there are errors, the receiver cannot detect those errors. And the scheme fails. So it's not perfect detecting errors. Only in some cases. So the green is what the receiver believes. The red result is what we, with knowledge of the transmitted receiver, know. Any questions before we move on? The result is the outcome of the error detection scheme. So remember what we're doing is sending data and to the receiver. And we're using what we call an error detection scheme. Ours is a parity check. The idea or the aim detect errors. The result is us saying or me saying, if I know what happens at the transmitter and receiver, did my error detection scheme at the receiver work? Well, in this case, the receiver decided there were no errors. There were no errors. Correct, correct assumption. In the second case, the receiver decided there are errors. There were errors. That's the correct result. It made the correct decision. And the third case as well. But in the fourth case, the receiver assumed that there were no errors. But there were errors. So the receiver made a mistake. The result is that error detection scheme failed in that instance. You must remember that the transmitter and receiver are different entities. So they don't know what each other are doing. But we as some entity that can oversee both the transmitter and receiver can determine the outcome or the result. Here, I mean, the cross error detection failed. Our algorithm didn't work as intended. Can anyone see when it will always fail? What are the conditions when this one bit parity check will fail? Why did it fail there? We remember the scheme is that we transmit odd. If we receive odd, okay. If we receive even error, that's the assumption of the receiver. Here we transmitted an odd number of ones. We had two bit errors. So if you change an odd number of ones two times, you'll still get an odd number of ones. And that's why the receiver thinks it's okay, but it's wrong. It's this even number of bit errors that caused it to fail in this case. If there's one bit error, if we start with an odd number of ones, we'll always finish with an even number of ones. If there's just one bit changed. But if there are two bits changed, if we start with an odd number of ones, we'll always finish with an odd number of ones. And that's why it fails in that case. When there's two bits in error, it will always fail. You can try other combinations. And with three bits, what will happen? Bits one, two, and five in error, it will work. Because if you start with an odd number of bits at the transmitter and change three of those bits, you'll end up with an even number of ones. And that would detect the error. If there's four bits in error, it won't work. So in general, if there is an even number of bits in error, parity check, we're using a single bit parity check, doesn't work. It's no good. Which implies that parity check is only really useful when there's few errors, one bit in error occasionally. So it's only used when there's a very low chance of errors. It works, especially with one bit, but if you have more, then there's a high chance that you'll get it wrong. So any error detection scheme, we say has some error detecting capability. That is, how many errors can it detect? And how many times does it fail? So different algorithms will have different capabilities. They'll be able to detect a certain percent of errors and then they'll fail at a certain percent. So we can talk about the capability of different algorithms. Every error detection algorithm will have some failures. We'll always have some failures. So different algorithms have been designed to try and reduce the probability of failures. You may have heard of CRC, the Cyclic Redundancy Check. CRC16 or CRC32 are common ones used, which have a better algorithm than parity check. They'll have less chance of getting this case of a failure, but still there's a chance of failure. That is, we miss the errors. Just some summary points on this scheme. It's maybe not clear here, but if you look at in other algorithms that, oh no, let's look at efficiency first. What's the efficiency of our data transfer in this case? The data or the payload, I have seven bits. That's what I want to get from A to B, but using this parity check, I actually transmit eight bits, one bit overhead. So in fact, I can say my efficiency is seven over eight, which is 87.5%. If I keep transmitting a continuous sequence of bits using this approach, what I can say, assuming that we don't have any failures, that if we always detect errors in terms of the overhead, 87.5% of the time I'm transmitting real data. 12.5% of the time I'm transmitting the parity check, the parity bit. So adding that parity bit introduces some overhead. Reduces our efficiency. But we used it so we can detect errors. Now really, if we wanted to look at efficiency and throughput in more detail, we would look at a number of cases and look at, well, how much data is received in error? And that's a more complex analysis. But we have one bit overhead out of every eight bits. So we say we're 87.5% efficient. In general, there are other algorithms, not just the parity check. And we'll see it on the slides, but if we have a payload of say K bits, not seven, but in general K bits, then we transmit N bits, e.g., our K was seven, and we transmitted eight bits, that is, we had a one bit overhead, then the efficiency is K divided by N. So if we generalize, we can say, for any error detection scheme, we start with our payload, our data, K bits of data. We add some extra information. In our example, we added one extra bit, but in others, you can add more than one bit. We say we add an error detecting code. And the total number of bits we get, if we add in the extra, we get N. In our example, we ended up with eight. Then the efficiency is K divided by N. Seven over eight, for example. How can we increase the efficiency? Well, make the number of bits we add as small as possible. Make N and K as close as possible to each other. If I have a thousand bits, K is a thousand, then I want N to be slightly more than a thousand, not much more, because we need to add some bits for the error detecting code or the parity bits, but we don't want to add too many. Now the problem is, in general, with error detection codes, for a given number of bits of data K, maybe we'll write it here. It's maybe best described on the slide, but the name will give it an error detecting code. If I have K bits of payload, and I transmit a total of N bits, then the difference, and minus K, is those bits that we add, like the parity bit. In general, it's called an error detecting code. The larger the code, the lower the efficiency. If we add more bits, it'll be less efficient. But the trade-off, this is the point I was trying to get to, the larger the code, better error detection capabilities. What that means is that the larger the code for a given piece of data K, the less chance we'll make mistakes at the receiver. The less chance we'll get those failures. So with error detection, we start with K bits of data. We add a code. The larger code we add, the worse our efficiency will be, but the better chance we'll be able to detect errors. So when people compare different error detection schemes, the code length, or the error detecting code, is something they compare them based upon. Maybe that's, to some extent, summarized in this picture, this diagram. So in general, error detection, the concept is we add extra information to the data we wanna send, and we call that extra information an error detecting code. In our example was the parity bit. That was our error detecting code. And the receiver checks. It does some checking based upon the algorithm. So in terms of our data, we have K bits of data. We attach the error detecting code. We end up with N bits to be transmitted. We transmit those N bits, and the receiver does the check. It compares the code and using the algorithm and makes a decision. Error or no error. The ability to detect errors depends upon the algorithm and the code length. So on the example I tried to illustrate, the code length is one thing that will impact upon the detection capability. Larger the code, better detecting errors. But we would need to study some other algorithms to illustrate that through an example, which we don't have time for. One of the other common algorithms is CRC. But there are a few others as well. So that's an example using parity check of error detection. Note that the receiver doesn't know where the error was. They just know binary. Yes or no? Error or not? And the receiver may sometimes make a mistake. It may think no errors, but in fact, there were errors. So it can fail. What do we do when we get errors? We'd like to fix them. It's no good to just detect them and say, okay, the bits are wrong. We'd like to fix them. Now one way to fix, the receiver receives, it detects an error, then it can ask the source, please send again. Send that same data again. And hopefully the next time there will be no errors on the link. Maybe there's no noise at this stage or no problem so that we receive it the next time and it's okay. So that's one way to fix the errors. But there's another way which we'll go through now. It's called forward error correction. Similar idea, but what we do is we take our data and instead of sending the data and some extra information, we encode that data using some algorithm and obtain a code word. And we send the code word. We don't send the data, but the code word represents the data. The code word will be longer than the data. If the data is k bits, the code word will be n bits. We transmit the code word and the code word is designed such that what the receiver can do is first check if that's a valid code word and check if there's any errors. And then if there are errors, try and fix them and get the original data back. So the idea with forward error correction is that we don't transmit the data, we transmit a code word representing the data such that it allows us to detect and correct errors at the receiver. We don't have to ask them to send again. We correct errors before retransmission or in advance. And that's why it's called forward error correction. So again, to explain this concept, we'll use a simple example and just one simple example to illustrate how we can correct errors. And the example will be a simple forward error correction encoder which uses a concept called hamming distance. So first introduce hamming distance. Very simple. We'd like to compare how similar two sequences of bits are. And hamming distance allows us to do this. Given two sequences like v1 and v2 here of the same length, both of these are six bits, the distance is the number of bits that differ if we go in order. So I'll write these two sequences again, one under each other and you'll be able to see that easier. Just the two sequences from the slide. What I want to know is how similar they are or how much different they are. And we can use the hamming distance to measure that. So we will ask, what's the distance or the hamming distance between v1 and v2? So v. Well, the way to find it, look at the bits and count the number of bits in order in the same positions which differ. The first bit of each sequence, zero and one, they are different. So have one that's different. The second bits of each sequence are the same. They're not different. The third bits are different. So there's two that are different. The fourth are the same. The fifth are different. So there's three bits which are different and the last are the same. So the distance is three. Look at the sequences in order and just compare the bits, count how many are different. But different across the two sequences in the same position. And that's what we call the hamming distance. And it's a measure of how similar those sequences are. If you had five zeros and then four zeros and a one, they're very similar. It's just one bit that differs. So the distance is one. If you have two sequences which are the same, the distance is zero. They are identical. This is not forward error correction but we'll use hamming distance in our simple FEC encoder. Any questions on hamming distance? We need to know that for the next step. Two sequences of the same length. Which bits are different? I just counted. One, two, three is me counting. Okay? First bit, zero, first bit of each sequence are different. So the green is just me counting. The first bits are different. One, not different. Different are two now. Not different, different. Now I'm up to three. Not different. I end up with three. Three bits differ. Now let's use this to do error correction. And the scheme is that in this example, we're going to start with two bits of data. I want to send two bits of data from A to B. But both A and B know this table. With two bits of data, there are four possible combinations. Zero, zero, zero, one, one, zero, one, one. So that's all I can send if I focus on two bits at a time. Instead of sending those two bits of data, I actually convert it to a code word. And in this example, I'm going to use a five bit code word. It can be different lengths. And the actual code word I'm going to use is defined in the table. What that means, if I want to send the data zero, one to destination, I don't send zero, one. I send zero, zero, one, one, one. I send the actual code word. And the destination B will receive the code word and do something with it. So first we send code words, not data. These code words were chosen and must be known by both the transmitter and receiver. So I think both the A and B have this table. They know it in advance. In a different example, they may be a different set of code words. There's 32 to choose from if we use five bits. Two to the power of five, we have 32 possible code words. With four possible data, we have to choose four of the 32 code words. But which ones we choose may be different in different algorithms. I've chosen just for this example, the four listed on the table. What's going to happen when the receiver receives the code word is going to check. Does it match one of the four expected or valid code words? The transmitter will only ever send these four out of all 32 possible code words. That's all they'll ever send. But with errors, the receiver may receive different code words. So what the receiver would do is check. Did the receive code word match one of these four? If so, then we get the data. If not, then it will try and find the nearest code word that it matches and assume that's the data that was sent. And the nearest will use the hamming distance. So let's do that with a few examples. We'll send data from A to B and we'll have some different types of errors and see what happens at the receiver. And the data in this example will keep it the same. That is, let me just write down that table. Exactly the same as on the slide in the last one. Okay, so I'm just copying that so I can see it when I do the calculations. This is known by the transmitter and the receiver. A and B, for example. And the data we want to send, let's choose some data to be, for the example, zero one. A wants to send zero one to B. That's the original data. So what the transmitter does is instead of sending those two bits, it sends a code word. Which code word? It looks up in the table, the second one here. Zero, zero, one, one, one. So this is from the transmitter's perspective. He's going to send the five bits instead of the two bits of original data. What we'll do is we'll look what happens when there are different number of errors or different errors occur across the link. So this is going to be transmitted from A to B. Then we're going to receive. And there are going to be some errors across the link and we'll consider what happens with different cases of errors. First case, let's consider the simple ones. What if there are no errors? We transmit this code word. There are no errors on the link. What do we receive? Well, we transmit these five bits. We'll receive that exact five bits. So the received code word, I'd say, zero, zero, one, one, one. So this is the simple case. Nothing goes wrong. The receiver receives these five bits. What the receiver does is checks. Does the receive code word match one of the four valid code words? These four are valid. All of the other code words are invalid. Not expected. Does the receive one match one of the four? Yes, it does. It matches the second one. Therefore, let's assume there were no errors. So we'll assume that no errors in this case. Coming up to help me. You all right? Let's assume no errors from the receiver's perspective. Why? Because the receive code word is one of the valid ones. It means we're going to assume that nothing went wrong and therefore the corresponding data received is zero one. Received data, zero one. Did this work? Did we get the correct data? Yes. The original data was zero one. I eventually received zero one, so it worked. I assume that there were no errors at the receiver, which was the correct assumption because there were no errors. So in this case, everything's worked fine as expected. Successful error correction scheme. There were no errors, so it wasn't hard to work. Let's consider the cases when there are some errors. Transmitting the same data, zero one. Let's see what happens. Let's say bit one bit is in error. The third bit. I transmit the code word. We want to deal with the same data. Zero zero one one one. And when it goes across the link, there's one bit in error and it's the third bit in the sequence. So what's received? Zero zero zero one one. The third bit is wrong. The receiver doesn't know the third bit is wrong. We do, but the receiver just gets those five bits and applies the rules for the error correction scheme. And the rules are first step. Compare the receive code word against the four valid code words. Does it match? Is this a valid code word? No, it's not one of the four. So that tells us error detected. If it's not one of the four, something's gone wrong. So we have actually inbuilt error detection here. So we'll say detected in this case. We've detected an error, but we want to also correct the errors. We want to fix it. How can we fix it? When we detect an error, we now compare the receive code word against the valid code words and find the one with the minimum distance. But that is the valid code words. I'll write them down. It'll be easy for you to see. The four valid code words. I have to remind myself. These are the four valid code words. We have an invalid code word. Let's find the closest match. What is the hamming distance between our receive code word and the first valid code word? So here we use hamming distance. How many bits differ? The first three are the same. The last two are different. So we'll say the distance is two. Now we do it for the next valid code word. The difference between this receive code word and the second valid code word, hamming distance of, calculate the remaining three hamming distances. That is 00111 with 0011. What's the distance? And then do it received with the next valid. What are the three distances there? Remember distance is simply the number of bits that differ if we go in order. Find the hamming distance from receive to valid code words. Next one, next one, one bit differs. This one, how many bits are different? Three, and the last one, how many bits are different? Four in that case. So that's the hamming distance from our received with the valid. Choose the minimum one. Why? Because what we're assuming is that, well we receive this, it's most likely this one, the one that's closest to. Most likely the receiver actually said this, but there were some errors. Under the assumption that we expect a small number of errors, then if the received one is very close to one of the valid ones, let's assume actually that was transmitted. So here's the minimum. We assume that this was the transmitted code word, so we correct the error. We perform a correction. And what's the data? Well, for the second code word, 00111, the data was 01, here, 01. Did this work? Yes, first error detection. The receiver detected an error. Did that, was that the correct result? Yes, because there was an error. And then the receiver tried to correct that error. It performed a correction. And it eventually got the data 01. That worked as well. What was transmitted, 01. So this was successful at error detection and correction. The first one worked, it assumed no errors and got the data immediately. The second case works as well. We detected errors and corrected the errors. We originally, we got the original data. Let's try a couple of other cases so you're clear on how it works. See what other outcomes may arise. Assume the first and fourth bit are in error. Look at what's received. Then look, is it a valid code word? Is an error detected? And if an error is detected, find the minimum hamming distance, the nearest code word, and try to correct. So go through that, it takes a few minutes to calculate the hamming distances, try that, and we'll see what people get. Remember, compare against the four valid code words when you detect an error. Remember, we expect to receive one of the four valid code words always. If we don't, must be an error. Because the transmitter always sends one of these four. If we receive something else, error detected. And then we try to correct. So in this case, what do we receive? With the first and fourth bit in error, we're going to get 10101. It's not a valid code word, it's not one of the four. So we say, error detected. Error detection worked here. Now, when there's error detected, let's try and fix it. See if we can fix it. And the way is find the hamming distance between the received and the four valid ones. Between the received and the first valid code word, what's the distance? How many bits differ? Three bits. Second one, two, third, last. Okay, so we want to get the nearest, the closest, the one with this minimum hamming distance. What do we get? Ah, there's two, all right? Two with a minimum of a hamming distance of two. What should the receiver do? Which one should I choose? Well, different options. Choose the first one just because we think we're lucky. Or choose randomly, okay? There's two to choose from. It's saying that I receive this, but it's close to these two ones. So let's guess it's one of these two. All right, so we think, well, maybe what they really said was one of these two. Now, if we try and choose one, let's say we guess, and maybe it's the first one. So let's use this, then we get the received data, zero one. That would have been a good guess. But if we guess the second one, we would get the received data, one zero. Transmit zero one, receive one zero, that's a bad outcome. So we don't guess, okay? Because if we guess in this case, there's 50% chance of getting it wrong and making a mistake at the receiver. So we don't guess, we just say, we cannot correct. We cannot correct this error. Let's leave it as is. We don't receive any data, and we must correct it in some other way. So this is a case where we say, say we cannot correct this, cannot perform a correction. We know there's an error, we detected an error, but with the current algorithm, we have no way to know or to try and correct what it is. So we'll say what's received, nothing. So this just performs error detection in this case, similar to parity check. Parity check didn't correct, it just detected. In this case, we've detected, but we haven't corrected the data. So we've got an error. How do we fix that? Maybe this is the time to ask the source to resend, okay? I realize there's an error. I don't have a way to know for sure which one it is. So maybe ask for a resend. So that's the right approach there. That's the good approach, because there were errors, we detected them. So that worked. We couldn't correct them, but not correcting is better than trying to correct and getting it wrong. If we tried to correct by guessing, say the third one, we would have got it wrong and got the wrong data. We would have thought we had correct data, but it would have been wrong. So this is an okay outcome. It worked, but just not as good as the previous case. One more, try the third and fourth bits. Third and fourth bits are in error, same original data. So zero, zero, the first two, then we get a zero, zero, and the fifth bit is the same as the transmitted code word. So this is the received code word. Valid or not, compared to the four valid ones? No, it's not valid. It doesn't match the four valid ones. So we say error detected, something's gone wrong. So same approach, compare, we could do it quickly. Compared to the four valid code words. Difference between received and valid number one? Just one bit. Between received and valid number two? Two bits. Received and valid number three? The first two bits differ? Received and valid number four? All of the bits are different, five bits. Now we have a unique minimum, we need a unique minimum. We perform our correction, we choose this one, we say okay, I receive this, it's very close to this one, so let's assume the transmitter sent this code word. And let's now assume the data received is the corresponding data for the first code word, which is zero, zero. What's the outcome? We have a problem here. We transmitted zero, one, using this approach, we detected an error because the code word received was invalid, then we tried to correct it, we found the closest one and chose the closest one. This is the closest to the received, choose that corresponding data, zero, zero. So that's what the receiver thinks it has. The receiver thinks, ah, I've gone well, I detected an error and then I fixed it. Now here's the data, zero, zero. But we know that the receiver made a mistake. The transmitter sent zero, one, the receiver thinks it got zero, zero. This is an example of our error correction scheme failing. Didn't work. And it's possible that we can, in the three cases we've seen here, the three outcomes. If there's no errors, no problem. With errors, we can detect and successfully correct them. We may detect them, but not be able to correct them, which is okay, but not as good as the first case. And we can detect them and make an error in trying to correct it. And that's a bad outcome. And in fact, there's another case that we could not even detect an error when there's errors. If I receive the code word, if I transmitted the same data and received the code word, one, one, one, one, one, one, zero, I would think it's okay and make a mistake. So there's different possible outcomes with our error correction scheme. We'd like it to detect and correct. If it can't correct, at least detect. Not make mistakes, like the last case. And with all error correction schemes, they have this error correction capability. They have different abilities in terms of all the possible data that it can receive, what happens with different types of errors? How good is it at correcting and detecting? And people can compare them that way. You could try some other combinations of errors. And you'd see what happens by seeing if it's valid. If it's not valid, find the minimum hamming distance. And then assume that's the data. So they're not perfect, but they can be designed to give high probability to detect and correct errors. Not 100%, but very high. Last thing, what's the efficiency? For every two bits of payload we want to send and get delivered, we actually have to send five bits in this example. We're 40% efficient with this. We have to send a lot just to get two bits through. So that's the problem with these error correction schemes. Generally compared to error detection, they require more overhead. And if there are no errors, let's say in a link with no errors and we use this scheme, then we spend a lot of time wasting our link because we're only using 40% of the link to send our real data. If there were no errors, then that's very wasteful. If there were lots of errors and we fix them, then maybe this is okay. So we need to compare on efficiency. Similar to error detection, the longer the code word in this case, relative to the data, if we increase five up to six, up to seven, the longer the code word efficiency goes down, but the ability to detect and correct goes up. So that's one example of a simple forward error correction scheme. There are more complex ones. We went through that case. Actually, that's all we have. Flow control is another thing that we'll consider when we look at the protocols for how do we retransmit? If we detect an error and we don't have forward error correction or we can't correct the error, we should ask the source to send again. There are some methods for doing that, which we call ARQ methods. We'll look at them after the midterm and there are similar concepts to use for flow control. So we'll introduce flow control after the midterm.