Placeholder Image

Subtitles section Play video

  • In a previous video we built this circuit that generates a valid VGA signal, and when we plugged a monitor in

  • we saw that the monitor recognized that it was in 800 by 600 mode.

  • And that's because we're sending at the right horizontal and vertical sync pulses for that mode.

  • We're sending a 3.2 µs horizontal sync pulse 38-whatever thousand times per second and

  • we're sending a 0.1056 ms sync pulse

  • 60 times per second. And the way this all works is we have a binary counter here that's counting from 0 to 264

  • you know over and over again, and it's counting at exactly 10 million times per second.

  • So we can look for these particular values to get the pulse width and the pulse frequency

  • to match exactly; and then same thing in the vertical direction, you know

  • we've got another counter here that counts each line on the screen from 0 to 628

  • and of course, you know

  • we measured all the timing and everything in the last video to make sure it matched the specs and it did and

  • so we saw the monitor recognize it as a valid signal. So if you want to know more about what's going on here,

  • I definitely recommend you check out the first video, but now you know

  • we probably want to actually display something on the screen.

  • And to do that, the VGA interface has a few more signals for red, green and blue. and

  • Because we're using the sync signals here to stay synchronized with the monitor

  • we can use our horizontal and vertical counters to keep track of what part of the screen the monitor is currently

  • "painting" at the moment. And so the 0 to 200 tells us where it is from left to right, and then the 0 to 600

  • Will tell us where it is from top to bottom and so as the monitor paints the screen

  • You know, left to right, top to bottom: the same way you'd read a page in a book.

  • These red green and blue signals is how we tell the monitor what colour pixel we want at that particular location.

  • In other words: because we're synchronized, we can use our counters to know exactly what pixel the monitor is.painting at the moment

  • So for example if I take just one bit from one of these counters

  • (so this is the the vertical counter) if I take those, you know 1 2 4 8 16s place

  • Let's say this 16 s placed bit right here

  • you know as we count down the screen from 0 to 600 down the screen this bit is going to flip on or off every

  • 16 scan lines.

  • So if I take that bit and hook it up to the the green signal and I'm hooked it up through a

  • resistor (for reasons that I'll get into here in a minute)

  • There we go

  • You know

  • You can see every 16 lines the green flips on and off and that's because as our article counter counts from 0 to 600

  • every 16 counts this

  • 16 places bit flips on and off because that's how binary counters work

  • Now if I hooked the red up here to the eights place in the same way

  • There we go

  • and now you now you can see the green and the red as well as

  • Yellow when the two mix and then of course, you know, I can also hook up blue

  • So, let me just do that for the sake of completeness

  • And now you can see the three primary colors mixed to give us actually 16 distinct colors

  • but you know as much fun as colorful stripes are what I really want to do is display a more complex picture and

  • for that to work

  • We need the pixel data stored in some memory somewhere

  • Normally in a computer the data for whatever's on the screen is stored in a part of RAM

  • that way the software running on the computer could just write new data to the same Ram location and the image on the screen will

  • Change right away, but I'm not gonna hook this to a computer at least not yet

  • So I'm just gonna store the image on an EEPROM and this is a 28 C

  • 256 EEPROM so it'll hold 32 k of data which should be enough for an image of some sort

  • and the way this will work is we already have our horizontal and vertical counters giving us an x and a y

  • position and if we feed all of those signals into the addresses of the

  • EEPROM

  • Then the EEPROM will give us a byte stored at that address and that byte could be the color of the pixel for that particular

  • XY location

  • So that's how we'll store the image in the EEPROM

  • But there's one weird issue which is because we went with the 10 megahertz pixel clock instead of 40 megahertz

  • we only have 200 pixels by 600 instead of 800 by 600 and

  • 200 by 600 is kind of a weird resolution

  • No

  • The pixels would be kind of stretched out because really what we're doing is we're repeating each pixel four times as we go across

  • So it'd be nice to maybe slow our vertical counter down. So we repeat each line four times as well

  • And it's actually pretty easy to do if we have our counter counting in binary like this

  • You know here we're just counting 0 1 2 3 all the way up to 16, you know, just counting in binary

  • Well, if we lop off that last bit

  • now it goes 0

  • 0 1 1

  • 2 2 and so forth up to 8 and if we lop off another bit

  • Then it repeat each number four times and only counts up to 4 instead of counting to 16

  • So if we just ignore the bottom 2 bits of our Y counter that all divided the counter by 4

  • We actually still have another problem which is the EEPROM. I have the

  • 22:56 it actually only has 15 address lines so we couldn't fit all these address lines here

  • Even if we wanted to so we've actually got to get it rid of at least three address lines in order

  • For it to actually fit in this EEPROM

  • So given what we've got with this EEPROM and to keep the right

  • proportions end up having to drop three bits from our Y counter and one bit from the X counter and that leaves us with a

  • Final image resolution of 100 pixels by 75 pixels which you know, I don't know it's maybe not the most impressive resolution

  • But I mean, what do you want for me? I'm trying to build a video card on bread boards

  • So 100 by 75 is is what we get. So let's hook the EEPROM up like this

  • I'll start by adding another breadboard and connecting power and ground to the EEPROM

  • Then I'll tie the right enable pin high since it will only be reading and it's active low and

  • Output enable and chip enable are both active low as well

  • So I'll tie them both low, so everything's enabled for output

  • Then the first seven address lines go down to our horizontal counter

  • and again

  • We're skipping the first bit and the next seven address lines go to the vertical counter and this time skipping the first three bits

  • So that's 14 address lines 7 for X 7 for Y. There is a 15th address line, which we're not going to use

  • So I'll just tie that to ground

  • So now we've got all of our address lines connected like this

  • So for each of our 100 by 75 pixels, we should be getting a byte of data out here

  • That'll presumably tell us what color that pixel should be

  • But how are we going to turn this 8-bit data into the signal that the VGA monitor expects?

  • well

  • the VGA interface has three pins red green and blue and each expects a voltage between zero and point 7 volts and

  • Depending on what that voltage is

  • Whether it's closer to 0 volts are closer to 0.7 volts

  • Determines how much of each color is mixed together to determine the color of the pixel?

  • But we've got eight bits here of data that are either 0 volts or 5 volts. How do we get something that's point 7 volts

  • well is the case where we have one voltage and we need a lower voltage and so we can use a voltage divider and

  • A voltage divider is just two resistors like this. So relative to ground down here

  • We've got 0 volts and up at the top. We've got 5 volts and in the middle here

  • It's going to be somewhere between 0 and 5 volts and how far it is from 0 volts to 5 volts

  • Depends on how big r2 is compared to the total resistance

  • So if r2 is half of the total resistance that is r1 and r2 or the same value then in the middle here

  • We're gonna have half the voltage. So two and a half volts if r2 were 10% of the total resistance

  • Then we'd have 10 percent of the total voltage or half a volt

  • So this expression just describes that?

  • You look at the proportion of r2 to the total resistance

  • And then that tells you how much of the total voltage you get

  • Now the VGA spec says that the red green and blue signals it says, you know zero to 0.7 volts

  • It also says it's got this 75

  • ohm input impedance and

  • You can roughly think of that as meaning that inside the monitor

  • Those red green and blue inputs are kind of connected to ground like this through a 75

  • Ohm load of some kind

  • so if we've got five volts and we want to get it down to

  • 0.7 volts as it's going into the monitor here. We can just add a resistor like this and that creates a voltage divider, right?

  • So we've got five volts at the top

  • We've got ground here at the bottom and we want this to be 0.7 volts here in the middle

  • Now if the monitors input impedance is 75, ohms

  • we can't change that but we can put whatever resistor we want here between our 5 volts and the input to the monitor and

  • You know to figure out what resistor that needs to be in order to get 0.7 volts

  • well, we could just look at this expression here and say you know

  • When would this expression equal 0.7 volts given that r2 is is going to be 75, ohms

  • well, we can put

  • 75 ohms in here for r2 and set it equal to 0.7 volts and we just need to solve for R

  • So 5 times 75 is is 375 and then R + 75 times 0.7 is gonna be 0.7 R + 52 and 1/2

  • Subtract that 52 and a half from both sides we get 0.7 R

  • Equals 3 22 and a half we can divide that by 0.7 and we get R equal to four hundred and sixty point seven. Ohms

  • So if we take five volts and we put it through a four hundred and sixty point seven

  • Ohm resistor will have point seven volts here going into our monitor, you know given that there's a 75. Ohm load inside that monitor

  • But ideally we don't just want point seven volts or zero volts going into the monitor here, you know

  • ideally

  • we'd be able to have a range of voltages between zero and point seven volts so we can get different brightnesses of red green and

  • Blue, yeah, so that we're able to have different shades of colors

  • so for example

  • If we wanted four different voltages from zero at 0.7

  • Evenly-spaced so we could get four different shades of red green and blue

  • We'd have to solve this equation essentially for each of those different voltages to find out what resistor we need to get that particular voltage

  • So that's what I've done here. That's what these different resistances are and

  • This is for you know, one-third brightness two thirds brightness, and then of course full brightness at 0.7 volts

  • Which is what we just we just figured out is four hundred sixty point seven

  • And we could use these different resistances to get these different voltages so that we end up with these different

  • Brightness levels for each of the colors and of course, you know, they don't make fifteen hundred fifty five point four

  • Ohm resistors they make you know fifteen hundred. Ohm resistors and they don't make

  • 720 two point nine. Ohm resistors, but you know, I've got 680 ohms which is maybe close enough

  • So if we use those resistors to build something like this that's got two inputs over here that can be you know

  • Either 0 or 5 volts and an output over here and check this out

  • You know if both inputs are zero like this then the output table. These are going to be 0 volts, right?

  • But if one input here is 5 volts

  • So the one hooked to the 1.5 cave' resistor is 5 volts and this is a zero then essentially we're kind of in this scenario

  • Here where we have, you know, approximately 1,500

  • 1,500 ohm resistor and we're gonna get about

  • 0.23 volts over here

  • But if we flip that around and we we don't have anything here and we have five volts down here

  • Then we're going through the 680

  • Ohm resistor and we're gonna have you know about 700 or well we're gonna have about 0.47 volts

  • But then if we have ones on both of these inputs, so both of these inputs are 5 volts

  • Well, then these resistors are going to combine in parallel and to combine resistors in parallel

  • You use this expression here, which is sort of the sum of the reciprocal of the sum of the reciprocals

  • So to combine 1,500, ohms and 680. Ohms in parallel like this

  • It's going to appear as a single resistance from 5 volts to this point over here of 468

  • Which is pretty close to here and so we're going to get 0.7 volts, so

  • this takes two inputs that can either be 0 or 5 volts and

  • gives us the 4 different possibilities that give us these 4 different voltage levels from 0 up to 0.7 volts and

  • So with just a couple resistors

  • we can take 2 bits of binary data and convert that into one of 4 different voltage levels from 0 to 0.7 volts and

  • If we do that for red green and blue

  • we can use six bits of data coming out of our EEPROM to get four different shades of red green and blue which combine into

  • 64 different colors and so this is the mapping for those different colors

  • If you're familiar with these hex codes for colors

  • But you can see the last two bits here controls how much blue there is now the middle two bits controls

  • how much green there is and then the first two bits controls how much red there is and

  • Then this here is what those actual colors look like

  • And so those are the 64 colors that were able to generate with a circuit like this

  • So let's actually hook these resistors up to the outputs of our EEPROM and to here the 1.5 K resistors

  • And of course, there's three of them one for red green and blue and here are the 680

  • Ohm resistors and so hook the first two data bits up for blue

  • And the first one is going to go to a 1.5 K resistor and then the next one will go to a 680

  • Ohm resistor, then the next two bits will be for green. So go to a 1.5 K resistor and then to a 680

  • Ohm resistor and then finally the last two bits are gonna be for red

  • The 1.5 k resistor and the 680

  • Ohm resistor and then we just need to tie this side of the the resistors for each color together

  • So they'll do blue

  • Green and red. And so now over on this side we should be getting that voltage between zero and 0.7 volts

  • So now we can try hooking this up to the monitor again

  • So here's our 15 pin vga connector and i've got the the same sync signals before in the ground, of course

  • But now i've got the red green and blue hooked up to pins 1 2 & 3

  • so we can hook up ground and hook up our sync signals as before so the horizontal sync and

  • The vertical sync and then the colors we could just hook up over on this side of the resistors

  • So there's blue there's green and there's red

  • now if we power up our circuit and plug in the monitor

  • So we basically see the same thing as before so the monitor comes alive

  • so it's detecting the sync signal but it's still a blank screen and

  • Of course, that could be because what's in the EEPROM is just blank

  • But I happen to know that this is an erased EEPROM and when you were to race an EEPROM it it just writes all one's

  • So we should actually see a white screen and we're not

  • but I think the problem is that if every address in the EEPROM is

  • Set to all ones then

  • We're gonna be outputting a white for every position and that includes even in the blanking time here

  • And we really shouldn't be putting out any pixels in this blanking time because well it should be blank

  • And in fact, this is one of those things that might actually damage a CRT monitor and hopefully we won't damage my monitor

  • But the way we can fix that

  • Is use these signals that were detecting here for the blanking intervals, right?

  • Because we're actually detecting when we're in this horizontal blanking interval

  • Right here with this flip-flop and we're detecting when we're in the the vertical blanking interval down here

  • So really what we need to do is we need to figure out are we in the blanking interval and those together?

  • and we could actually use the result of that for the output enable signal for our EEPROM so we can essentially turn the output of

  • The EEPROM off if we're in that blanking interval

  • so what I'm going to do is add a NAND gate here and I'm using a NAND gate so that the output is

  • inverted because our chip enable or not our tripping well actually both

  • But the output enable which is the one we're going to use the output enable is active low

  • So that way if if two inputs here are high

  • then the output will be low and then the two inputs that we'll use is well look at if we're in the display period for

  • horizontal and the display period for vertical

  • so, let me hook up power and ground for our NAND gate and

  • so the first input here is going to say are we in the horizontal display period

  • So in other words, this is saying are we in this time here?

  • and then the next input is going to say are we in the vertical display period

  • So that's going to say are we in this time here vertically?

  • If the answer is yes

  • if we're in both of those then what we want to do is we want to take the

  • Output of that and use that instead of just always tying our output enable low. So here we'll say output enable

  • Only when both of these conditions are true

  • So now let's reconnect our monitor and see what we get

  • And that's still not working

  • But it's possible that I've got these mixed up and so I'm actually outputting only during the blanking interval

  • So, let me just switch this over to

  • the

  • inverted outputs on both of these

  • And there we go now it actually looks like we're getting looks like a white screen

  • So if we want to display something a little more interesting then we've got to come up with a little more interesting image

  • Let's find an image. That's nice and colorful. This looks good public domain. That's perfect

  • So I'll download I guess, you know, we're gonna reduce the resolution here quite a bit. So it doesn't matter too much

  • So then if I load that image up in Photoshop, we can resize it

  • So we want our image to be 100 by 75

  • So 100 by well make it 114 by 75 and then we can crop it to 100 by 75

  • Okay, so there's our image with the resolution that we have on our screen. It's now we need to change the color modes

  • Who are using indexed color and we want a custom palette?

  • and

  • So these are the 64 colors that we can produce with our resistor voltage dividers and they're also in the in the right order

  • so for example an index of 8 is this

  • You know green color and if we have an 8 in our EEPROM then that's going to produce that same green color

  • So it's pretty important that we have the right colors in here and we have them in the right order

  • So if we apply that

  • This is the image we get so those are the 64 colors that we support and it's a 100 by 75

  • So that is that is the best our wonderful breadboard video card can do so, let's go ahead and save this

  • We'll call it image dot PNG

  • And if we actually look at what's in that file if we see, you know, there's more than just a pixel data, right?

  • There's a header here PNG. There's you know appears to be some XML stuff in here

  • So there's a whole bunch of stuff in here that we definitely don't want to write to our EEPROM

  • so what we've got to do is we've got to convert this PNG data into the pixel bytes that we want to put into our

  • Indoor EEPROM and the best way I can think to do that is just with a little Python

  • Script, we can use a Python image library to make a little bit easier. So pale is this Python image library

  • And we can open up an image file

  • and then we can load the image and when we load the image what we get is we just get a

  • two-dimensional array of the pixels and

  • because we're using index colors with 8 bits and

  • You know, we've got our colors in the right order here with the right index values

  • the pixels that we end up loading are going to be the values that we want to actually

  • output from our EEPROM to get those particular colors

  • So really what we want to do is we just want to write all those pixels to a file without any of the PNG header

  • Information without any compression without anything like that

  • We just want to write the raw pixels to a file and then we can write that file the EPROM

  • That's what I'm gonna do is just go through all the pixels. And since our image is 100 by 75

  • I'll just go through all 75 lines and then go through all hundred pixels per line

  • and then I just want to write the value of that pixel to a file so

  • I'll create an output file

  • just call it image bin and we'll just write to this as a binary file and

  • What we'll write to it is we'll write a character that has the value of the pixel

  • so the pixel is going to be coming from our pixels array and it's just gonna be at the

  • XY value that we're at

  • So if we run this that'll create that image bin file

  • And if we look at the image that bin file what we should see in here is we should see all of the pixels

  • so, I don't know if this looks like a bird to you, but

  • One sign that we're on the right track here is that all of these values in here are less than 64?

  • Or while they're in hex, but they're less than 40 hex which is which is 64

  • So at least everything seems to be you know in the right range

  • But this isn't quite how we want to organize the data in the EEPROM

  • because remember we're using

  • 7 bits for the exposition and 7 bits for the Y position and so because we have a hundred pixels per row

  • We have this X counter that goes up to 99, but once it gets to 99

  • It doesn't just go to 100

  • it goes back to zero and then we increment our Y position and so the actual address in the EEPROM will jump from 99 to

  • 128 because these all go to zero and then this bit will be a 1 and that's the hundred twenty eights place

  • so in the EEPROM really even though we only have a hundred pixels per line on the screen in the EEPROM we want to take

  • Up 128 pixels per line, but that's easy enough. We can just for each line instead of a hundred we can just do 128 and

  • Then because we're writing that 128 times we'll end up writing 128 things to the file. So let's run the conversion again and

  • we get an error so image index out of range and that's because you know

  • our image only has only has 100 pixels across so

  • You know when we're trying to get pixel 128 or even pixel 101 or 100 that pixel is not actually in our image

  • So what we can do is we can just try to catch that condition

  • So we get an index error when we try to get that pixel. That's not actually part of our picture

  • What we can do is we can still write to the file

  • But the character will write to the file would just be I mean, it could be I guess we'll just write a zero

  • So let's run that and now if we look at our image

  • We still see the data but what we see is we see, okay

  • This must be the first hundred pixels, and then we have a bunch of zeros that Pat it out to

  • 128 and so you can see like this block here

  • That's the first line and then this next block here with all the zeros padding it out to the end

  • That's the next line

  • And so this should be the format of data that we want to put into the EEPROM

  • Now I suppose I could use the EEPROM programmer that I built in a previous video

  • But in this case because I've got all the data in a file and everything already

  • It's probably easiest just to use a commercially prom programmer. It's also a lot faster. Let's pop our EEPROM out put it in the programmer

  • Then I'll use Mini Pro which is just an open source EEPROM programmer tool that works with this programmer and

  • Will tell it we're using the 1828 C 256 which is the EEPROM

  • We've got and we want to write the image bin file to it and it says incorrect file size

  • 9600 so that's because I guess it's expecting a file. That's the exact size of the EEPROM and we have a 32 K EEPROM

  • So we need to give it a 32k file

  • And the reason our file is is smaller is because our Y is only counting from 0 to 74 even though you know

  • This is 7 bits so it could go up to 128

  • And actually there's an a 14 right that's that's this extra address line that we just tied to zero

  • So there's actually another 8 bits here

  • So our Y value really could go from 0 to 255

  • But we're only writing the first 70 75 values of that and that's just so that our you know image aspect ratio makes sense

  • We can do the same thing here. We can just change this to 256 and

  • Then anything that's out of range will just write a zero to the file

  • So let's reconvert and then if we take a look at our image file

  • you can see the image but then if we go all the way down to the

  • you know if we get all the way down at the bottom it says

  • we have got a row of zeros and then I think this star just means everything is zeros between there and

  • Eid 0 0 0 which is 32,000

  • So let's try to write it again. And there we go. It's writing it

  • And so now let's put our EEPROM back in and see if we get the picture of that bird

  • Hey and there it goes and

  • So this is our completed video card, but you know, it's producing an image from the ROM. So I'm going to call that a success

  • Well, you might notice these thin black vertical lines and I think that's because the ROM I'm using is relatively slow. Yes

  • I'm using a 10 megahertz clock which means it's counting 10 million times per second or you know

  • Once every hundred nanoseconds remember the monitor still assumes I'm using a 40 megahertz clock

  • so really the monitor is expecting a pixel every 25 nanoseconds and

  • So here's the problem if we look at the data sheet for the EEPROM that we're using

  • There's a delay from when the address goes valid. The address lines are valid to when the output is valid

  • That's this TAC C or access time and if we look at access time here the addressed output delay

  • It's a maximum up to 150 nanoseconds for the dash 15, which is the one I'm using

  • Well 25 nanoseconds per pixel

  • 150 nanosecond delay could mean up to six pixels could be

  • invalid in this in this period from when the address changes to when the output is actually valid and you know

  • It makes sense that sometimes invalid might just mean that the output is zero

  • And so I think that's why we sometimes see a few black pixels like this

  • Now in a computer like I mentioned before the image would be stored in SDRAM

  • Which is designed to be very fast access for this very reason

  • And of course the you know the software running on the computer could write new data to that RAM and the image would change right?

  • away

  • whereas here the only way to change the image is to reprogram and/or swap the EEPROM which as

  • You can see even if I speed it up when I edit. The video is is pretty slow

  • But you know, that's not really the point is it, you know

  • Really the goal was just to get some kind of image on the screen and I'd say this is a success

  • And if you want to try this yourself, you can head over to my website

  • I've got schematics data sheets and where you can get all the parts and as always, you know

  • I want to thank my patrons for making it possible for me to create videos like this as you can imagine

  • these were rather time-consuming videos to plan out and produce and

  • without the support of these people and all my patrons who are just viewers like you

  • Making this kind of video just wouldn't be possible. So, thank you

In a previous video we built this circuit that generates a valid VGA signal, and when we plugged a monitor in

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it