As we all know, computers are equipped with all sorts of input/output devices. And likewise, the head computer can also be connected to some input/output devices. And in this unit, we're going to talk about how we use machine language to control and manipulate these I/O devices. So, we start with the basic architecture, that we've seen all along. But now, we are going to extend this architecture with two fancy I/O devices. We're going to have a display on it, similar to your screen. And we're going to have a, a keyboard which is actually identical to the keyboard that you are currently using. These devices are sometimes called peripheral because as you see in the picture, they exist outside the computer. They exist somewhere in the periphery of the computer. And here is how we actually use them. Well obviously, we use the I/O devices in order to communicate with the user. We show some pictures or animations, or anything that we want to show to the user using the display unit. And we acquire inputs from the user using the keyboard. Now obviously, we have some more devices like a mouse and microphones, and so on. But for now, let us talk only about the two most important device units which are the the display unit and the keyboard. How do you control these devices? Well, if your lucky to work in a high level environment, you know, if you use languages like Java or Python. Well, in that case, you have numerous libraries that provide all sorts of fancy way to manipulate these devices. You can create graphics, animation audio, video and so on. However, if you work at the low level that we are operating on, the only thing that you have is bits. So you have to be very clever about it and you have to figure out a way to use these very spartan zeroes and ones in order to do something useful and, and display and acquire information from users and to users. Now you may be wondering how do we use the high level in order to to manipulate I/O devices because this is also something that we have to to learn and understand how these libraries work. How do you draw a line? How do you draw a circle? And so on. Well, this is something that we deal with in the second part of this course. So if you want to learn about the softer hierarchy, if you want to learn about the design of high level languages and the I/O libraries that extend them. And how they operate also how they communicate with the operating system, this is something that we do in the second part of this course. In this part of the course, we deal with the hardware only. So, once again in this course, we're going to talk about the very clever ways in which we use bits to manipulate these devices. So, the first thing that we'll talk about is how to manipulate the output or how to manipulate the display element, also called screen sometimes. Well, how do you do it? Well the most important player in this in this game, is something called a screen memory map. And the screen memory map is a designated area which is part of the data memory of what is sometimes called RAM. So the deal is such, that the physical display unit is continuously refreshed from the contents of the memory map. And this happens many times each second. So, if I'm a programmer, and I'm restricted to working with zeroes and ones only, if I want to write something on the display unit, what I can do is simply manipulate some bits in the memory map. And I can count on, on the fact that in the next refresh cycle, what I change in the memory is going to be reflected on the screen. Now obviously, I have to be very careful about it and if I want to write a text like hello world, well it's going to take a lot of work. You know, I have to turn on and off pixels in very specific locations in order to affect this particular output. So, we'll do some of this today and we'll do some more fancy input/output operations, some much more fancy operations in the second part of this course, as I explained as I explained earlier. All right. So let's delve into the the screen memory map. Now, this is how we are used to think about display units. But as far as the hack computer is concerned, the display unit is the following obstruction. It's a table, or a matrix, consisting of 256 rows and 512 columns. And in each intersection of a, a row and a column, we have what is known as a pixel. This is a black and white screen, so we can either turn the pixel on or we can turn it off. This is the physical display on it that the hack computer assumes. Now how do we control it? Well, as I just explained, we have something called a memory map. And the memory map is a sequence of 16-bit values. Every one of these values is sometimes called a word. So we have altogether, 8k, 16-bit words. Why do we have 8k, 16-bit words? Because it turns out that 8k times 16 gives something like 13,000 and something, and this is the number of pixels that we have on the physical display unit. So, for every pixel on the physical display unit, we have a bit that represents this pixel in the screen memory map. And if I want to turn on this pixel, I put one in this bit. If I want to turn it off, I put zero in this bit. So, in order to understand and, and control these bits judiciously, I have to come up with some mapping that describes exactly which bit corresponds to which pixel. Now this is a little but involved because on the right-hand side, I have a two-dimensional obstruction. And on the left-hand side, I have a one-dimensional obstruction, and I somehow have to connect the two. So how do we do it? Well, first of all, you should notice, and I'd like to re-emphasize the fact that when we access memory, we can only retrieve 16 bits in one chunk. You know, we cannot access individual bits. If I want to access an individual bit, I have to figure out, first of all, in which word this bit resides, so to speak. And then I have to retrieve the entire word, do something to this value. And, you know, manipulate this particular bit and then I have to take this value and put it back, write it back into memory. So the read/write operations are always 16-bit operations. So I take the 16-bit out, manipulate something and put it back. All right? So what is the mapping? Well, here it is. The first 32 words in the in the memory map. Correspond to the first row in the display on it. Okay? So the first pixel that we see here and actually you can see it in the picture. We see that the picture begins with the four black pixels and indeed, we see four ones at the top of the memory. Then we have zero, one, zero, one. White, black, white, black and so on and so forth. Okay? So that's row zero, then we have row one, all the way down to row 255. Okay. So this is the first mapping that we have to to bear in mind. Now suppose that I want to manipulate a certain pixel on the screen and pixels on the screen are characterized by a row and a column. How do I map this row-column pair on the right register in the memory map? Well, here is how I do it. Well, first of all, I multiply row by 32 and then I compute column divided by 16. And this by the way is integer division. Namely, I throw away the remainder of the division. So for example, if column equals 18, then 18 divided by 16 is 1. So, I take the result of this integer, integer division. I add it up to 32 times row and this gives me the address of the register that they have to manipulate in the respective memory map. Now notice the word screen. Well, what does screen means here? Well, in the hack architecture and in this course, we are going to implement the screen memory map using a chip called Screen. So we're going to have an 8k chip called Screen, which behaves exactly as a memory unit. You know, we can, you can retrieve data from it, you can write data into it and this chip will, will serve as our memory map. However, when we build the overall computer, this chip is going to be part of the data memory. So the data memory or the RAM will consist of several chips and the screen will be one of them. You know, that's exactly how we described it before. We said that the memory map is part of the data memory. But notice that once you take this Screen chip and put it in a larger memory context, the base address of the memory map changes. So, if I access the Screen chip, I use the address that you see here. But if I access the overall RAM, I have to take this relative address and add to it the base address of the memory of the memory map in in the overall memory, which happens to be 16384. So this is just a technical detail. You know, if you want to write to the screen using the screen chip directly, use the first meth, the first algebraic expression. And if you want to if you are told that the Screen is part of a larger memory, you have to add up. The the base address. All right. So we have this 16-bit word and then we want to manipulate a particular bit inside it, which bit is it? Well it turns out that this bit is the column modular 16. It's the remainder which remains after we divide column by 16. So we get the number, which is between zero and fifteen, we manipulate this bit, we, we turn it to zero or to one. We take the resulting vale and we write it back into the RAM. Okay? That's the, if we won't do it, we won't achieve anything. Right? We have to somehow write it back into the memory map and in the next refresh, refresh cycle. What we just did is going to change the pixel in the in the outside display. I guess that some of you are kind of shocked at how much work it takes to to turn on, on and on, on or off one, one pixel, but that's it. That's, that's the reality. You know, if you work in a very low level in the level of of bits that's what you have to do in order to control the screen. Now, I didn't work out all the algebra. You know, this is something that you can do on your own. It's it will take a few minutes if you want. But you can just, you know, take a example. Let's say that you want to change bit the bit in the fourth row and in column number 55. You know, workout the numbers and convince yourself that you are going to access the right bit in the memory. Once again, I want to emphasize that one in three, the the fetching of the value and writing the value back are regular RAM operations. Read, write. And we discuss it before when we talked about memory units in general. Okay. Now, I also want to give you an example of how this thing actually works inside our hardware simulator. So, I'd like to load the Screen chip into the hardware memory, manipulate it and, and you can see in your own eyes. How it's going to actually change the screen and and manipulate the pixels. So let us load the built-in Screen chip. So we look for a screen and here it is. Loaded it. I can inspect the HDL code and see that indeed the Screen shape is a built-in chip. And it's a memory chip and if I look at the memory pane, in the output panes I see that it has the typical memory chip interface. It has an in input and out output a load bit that must asserted before our right operations and it has an address that enables me to select the register on which I want to operate. Another thing that we can observe is that the Screen built-in chip has a GUI side effect, which is this panel here, which represents or simulates a physical screen consisting of 512 columns and 256 rows. And every one of these rows is represented in the screen memory chip by 32 registers as we explained in the lecture. So lets say that we want to turn the first 16 pixels of row number 3 to black. S, in order to do this, we have to get to the register that represent the first 16 bits in row number 3. So we do 32 times 3, which gives us 96. This is the address that we have to manipulate. So we write 96 in the address input. We assert the load bit, because we are going to write something into the memory. And we have to write one, one, one, one, sixteen times. And it turns out that one, one, one, sixteen times in decimal and two's complement is minus 1. If you are not convinced we can turn the representation to binary and we see that indeed we got 16 ones. Let's turn it back into decimal, which is easier to read. And, we see that you know, it's very nice that we entered all these values into the memory but we haven't ran the clock, so, nothing really happened. You know, this is a mary, memory device. So, let's run the clock. And, we see that once we run it, we get, two things happen. First of all, the memory now contains this value in address number 96, but also, we have the side effect of seeing 16 black pixels at the beginning of row number 3 in the physical screen. [SOUND] Now, let us write some other arbitrary value and some other arbitrary address in the screen. So, we go to the address input. We pick up some arbitrary address like 3000, 3035. And, let's pick up some arbitrary value like 17 that we want to write into this address. And I'm not sure how many ones we have in 17. Let's turn the binary on, and we see that we have only two ones. So, this is not going to be extremely visible. But, in any rate, let's run the clock and indeed we see that these two babies popped up right in the middle of some obscure screen location. Which happens to correspond to the register that we manipulated in the screen memory man. So these two pixels obviously correspond to the two ones that happen to be the only two one bits in the binary representation of 17. So, this has been a demo of manipulating the physical screen using the respective memory map the screen chip that controls it. So, the next thing that I want to talk about is the input unit. How do we control and manipulate the keyboard. Well, the physical keyboard is connected to the computer using a cable. If you will trace this cable, you will see that it goes into an area in the RAM which is called keyboard memory map. You know, just like we had the screen memory, memory map, we also have a keyboard memory map. And, this is the representative of the keyboard inside the computer architecture. Now, it turns out that in order to represent the keyboard, you don't need more than 16 bits. So, the keyboard memory map is a single register, 16 bit register, which is called, keyboard. And, this is how the connection works. We have a special chip called keyboard which once again is simply a 16-bit register. And in the next uh,uh, few minutes I'm going to describe how this thing actually works. So, we'll do it using examples. When a key is pressed on the keyboard, the key's scan code, which is an agreed-upon value, travels through the cable and appears in the keyboard memory map. For example, if I press k, there is an agreed-upon value, which is, happens to be 75, a completely, well, not exactly, but almost an arbitrary value. In this value, 75 is going to appear in its binary manifestation in the in the keyboard chip. All right, I take my finger off and I click something else, like 4. Well, 4, you know, it's true that it's a number, but, but on the keyboard it's yet another symbol. So, the scan code of 4 happens to be 52, so, if I click 4, I see the number 52 appearing in the keyboard memory map. If I click space, well, space is yet another symbol. I see the number 32 appearing there. If I click, up arrow, it's yet another symbol, I see the number 131, and so on and so forth. Every key on the keyboard has a scan key which represents this this selection inside the computer, using a binary code. All right. So, what we have here is the complete character set of the Hack computer. These are the keys that the Hack computer recognizes. It's a subset of the keys that you have on your regular keyboard, but it's sufficiently rich subset for our own purposes. Obviously, we could have represented all the other keys, but we decided to represent the subset of keys only. And, by the way, if you have 16 bits you can represent numerous keys and and letters in many different languages and, and it's more than enough. Those of you familiar with the notion of Unicode or ASCII can make the connection between these notions and in what we do here. It's essentially the very same very same idea. And by the way, when you don't touch the keyboard, when, when nothing when the keyboard is idle, the number that we see in the memory map is 0. So, that's how we can tell if a keyboard is actually being used. The memory map once again, is this 16-bit register. And, if you want to check if which key is currently pressed, all we have to do is probe the contents of the keyboard chip. In the Hack computer we probe the contents of RAM in address 24576. Because, this is where the keyboard memory map, memory map happens to reside. That is, when we are going to build the overall computer, we'll do it next week. We're going to connect several chips together. We're going to, to begin with some regular memory units, and then we're going to add to it the screen memory chip. And, finally, we're going to add the keyboard, and the keyboard in this overall address space is going to be located in the address 24576. So, if I want to know if someone is pressing the keyboard, I have to look up the value of this particular memory register. If the register contains 0, no key is pressed. If the register contains some other number, well, I can tell which, which key was pressed according to the to the scan code. According to this number. So, to make this thing more vivid, I'd like to give you a demonstration of how that your physical keyboard is connected to the Hack computer through this keyboard memory map. So, that's what we'll do next. Let us load the built-in keyboard chip. And, here it is. Let's take a look of the HDL code and we see that indeed, keyboard is a built-in chip. And, if we look at the chip interface, we see that it's a read-only chip. It has no input pins at all. It has only one output, which emits the value that is currently stored in the keyboard chip. Now, this keyboard chip also has a side effect, which is, that the keyboard chip is connected to the actual keyboard that I'm using on my computer, on my real computer. And so will be the setting at your end if you, if you use a hardware simulator. The hardware simulator is connected to your physical regular keyboard. And, if you touch the keyboard, if you press any key on the keyboard, the scan code of this key is going to be emitted by the built in keyboard chip. So, let us test this and I'm taking my finger now and I'm pressing the key "g". And nothing happens, well, nothing happens because I have to enable the keyboard, so, I do it by clicking this button here. So, now let us click "g" and I'm holding my finger down and as long as I hold my finger down, I will see the scan code of "g" which happens to be 71. Emitted by the built-in keyboard chip which acts as the keyboard memory map. So, I'm lifting my finger now and as you see, the keyboard chip now emits the value of 0. Which means that none of the keys of the keyboard are presently pressed. Let's try another, another key. I'm, I'm, I'm going to press space, so pressing space. And, I see that the scan code of space, which happens to be 32 appears. Let me press down arrow, and down arrow happens to be 133. Let us press a digit, say 8. And, 8 happens to be associated with scan code of 56, and so on and so forth. So, this has been a demonstration of how we can figure out which key the user is currently pressing on the keyboard, and once again, recall that if the user is not pressing anything, we're going to see 0. So, this has been the unit in which we broadened our perspective, so to speak, and added input output units to the computer. And the the most important part of this unit was to to give you an idea of how you as a programmer can actually control these input/output units.