these little LCD modules are extremely
common but what's it take to hook one of
these up and get it working well it's
got these 16 pins that are used to
interface with it so if we just feed the
right signals in we ought to be able to
get it to do something and I've got this
little computer that I've been building
that so far I've just programmed to
blink some lights but now instead of
using these signals just to turn these
LEDs on and off like this let's use them
to feed in whatever needs to be fed into
this display to make it do stuff let's
hook that up so I get these LEDs out of
the way and I'll get the resistors out
of here and I'll install one of these
LCD modules and and these come in
different colors that blue is pretty
common I'm gonna use the yellow one just
cuz I think it shows up a little bit
better in the video but I'll start by
hooking up power to the display so these
first two pins are four five volt power
and VSS is ground and then VDD is five
volts so it's the power for the module
and so the next pin here is v-0 and
that's for adjusting the contrast of the
display and really all we need to do
with it is tie it to ground through a
resistor to set the contrast so I'll use
a 10k variable resistor so we can adjust
the resistance to adjust the display
contrast and I've already got the ground
line here so I'll hook one one leg of
this up to that ground and then the
middle pin will hook over to the v-0
input and now we should be able to just
turn this and adjust the display
contrast and then the rest of the pins
here are just the signals that we'll
have to hook up to the computer's i/o
lines here in order to communicate with
the display except for the last two pins
a and K here there's actually for the
backlight for the display so the display
lights up and a is the anode for the
backlight LED so hook that to five volts
and K is the cathode so I'll hook that
to ground and we can hook this directly
to 5 volts like this because the module
has already got a current limiting
resistor in it so we'd have to worry
about blowing up that led by putting too
much current through it so we can hook
it directly to 5 volts and we still
haven't hooked up any the signals so
it's not gonna really do much yet but
let's up power it on anyway just to I
think it's sort of make sure
and the backlight work so that's good
and nothing's on fire so that's also
good and you know we can check the
contrast setting too so because that
ought to work and so there we go so this
is this is obviously maybe too dark and
if we go the other way that's maybe too
light so if I kind of set it somewhere
in the middle there that's probably
about right there in the middle so
hopefully if anything we're on the
display we'd be able to see it but of
course you know we're not sending
anything to the display yet so you know
it's probably good we don't see anything
there but let's look up the data line so
we can actually send data to the display
so you can see they're actually eight
data lines here so d0 through d7 so I'll
just hook up all eight of them to the
sixty five twenty two interface adapter
here and I'm hooking these up to the
same eight bits that I originally have
those LEDs hooked up to because we know
we can set those pins to whatever we
want and you know actually I technically
don't need to hook up all eight of these
the display actually has a mode where
you can do everything with just four
data bits which is a nice feature
because it means you know we wouldn't
have to hook up as many wires or we
wouldn't need to use as many pins on the
65 22 but the 8-bit mode that I'm
hooking up here is a bit simpler to use
so I'll start there but you know maybe
if you're doing a project like this
yourself and you know you can get all
the parts over Ethernet slash 6502 but
you know whether you get the parts for
me or somewhere else if you're doing a
project like this you might want to try
figuring out for yourself how to do it
with just four bits but the 8-bit mode
is a good place to start because that is
going to be easier for us to use and
either way there are also a few control
signals that we need to hook up so this
are s RW and E pins are additional
control signals that we need along with
VA data lines
unfortunately the 65 22 interface that
were adapter that we're using has two
8-bit IO ports that we can use so we can
just hook up these three control signals
to three more io port pins over here and
we'll be able to control all the things
so hook up this EEP in the RW pin and
the RS pin and so those are all the pins
we need to hook but what do these pins
even for well we need to dive into the
datasheet to figure out how this all
works and this is actually the datasheet
for the interface chip on the module so
it's underneath this blob here it's not
the datasheet for the entire module
which which actually means we don't
really care about half of what's in here
you know because on one side you know
we're talking to the chip through this
you know the eight data signals plus
these control signals are SR W and E
that we just hooked up but the other
side of the chip actually talked to the
actual else
d screen and so it's got a whole bunch
of pins and so you know the the chip
itself has tons of pins and we don't
really need to worry about because most
of them are these like comment and
segment pins that go off to the actual
display and and control which pixels on
the display are set and actually the
display that we're using forty by
sixteen isn't even enough so there's
there's actually a little expansion chip
here as well and so there's extra pins
that interface to that expansion chip
but we don't have to worry about any of
that because someone else has built this
module and taking care of figuring that
out so we can just ignore you know
roughly half of what's in the state of
sheet and really just focus on this
interface here that we're connecting to
so we look at this mpu interface and MPU
is micro processor unit which you know
we're building a micro processor
computer then we see the eight data
lines that we've hooked up as well as
the RS RW and e signals that we also
just hooked up and the way this works is
we've got these eight data lines going
in and there's a data lines either
access the data register which stores
eight bits of data or the eight data
lines can access the instruction
register which also stores eight bits of
data and the way we select whether we
want to send data to the instruction
register or the data register is with
the register select signal that's that's
what this RS is register select so if
register select is zero then any data we
send in here is going to go to the
instruction register and so that might
be where we send commands to initialize
the display or clear the display or move
the cursor around things like that but
then if register select is high then the
data that we send goes into the data
register and that would typically be how
we send whatever characters we want to
actually appear on the screen because
then that goes into the data display Ram
which stores all of the characters that
are currently on the screen there's also
a read/write signal as we can actually
read information from the display module
to and we aren't just writing to it for
example we could read what's in the the
data registers to get data out of the
display Ram or you know we could read
with register select Lo and actually we
wouldn't read the instruction register
when register select is low we actually
end up reading the address counter as
well as the busy flag so those come out
as well so there's data we can read and
write so we have a readwrite flag there
and then finally the the e pin is the
enable signal so for any of the reading
or writing we might do here they've been
talking about the actual read or write
doesn't happen until the enable signal
is is toggled high so so that's going to
be important so let's look at the
assembly code we're using to control
these signals this is the program ahead
running and if it's a pattern of
five zero hex out on the eight bits that
we had there and then it uses this
rotate right instruction to shift the
the bit pattern over each time through
this this loop here but first it
initializes the i/o interface chip
that's what these first two lines here
are this address six zero zero two is
the data Direction register that says
whether these eight bits here on the on
the right that we're using are whether
we're using those for input or output
I'm sorry by storing FF in that register
we're saying that those signals are all
outputs and actually we can make this a
little bit clearer by defining symbols
for these different addresses so instead
of just saying six zero zero two we can
define some symbols up here so port B is
at address six zero zero zero and port a
is at address 6 0 0 1 and port a is the
eight bits on the left here so we're
just going to be using the top three of
those bits and then port B is the eight
bits here on the right that we've got
hooked up but then in the code once we
define those addresses here instead of
saying store a6000 we can say store a
port b this is the same as it was before
but hopefully maybe a little bit easier
to make sense of and then the data
Direction register for port b is at six
zero zero two and the data Direction
register of report a is at six zero zero
three so now i can change this to store
a DDR B you know to make it a little bit
more clear that this FF is is setting
the direction of the data for port B and
then if I want you know maybe it's not
clear what this FF even means because
what we're doing is we're loading FF
into the a register and then we're
storing that to address six zero zero
two which is the date of direction for
port B but the reason we're using FF is
because FF in binary is just eight ones
so if we want we can actually write out
the binary to make it even clearer
instead of a dollar sign if I use a
percent that means the number is binary
so I can just have eight ones and then
that's going to be the same number as FF
in hexadecimal and then here maybe it's
more clear that each of these ones
indicates that that particular bit
should be an output and of course I
never hurts to add a comment explaining
what we're actually doing and then for
port a we can actually do the same thing
but here we just set the top three bits
as ones in order to configure just those
first three bits as outputs and then if
we store this to the data Direction
register for port a now
set just those 3 bits on port a is
outputs and so here we're setting just
the top 3 pins on port a to output so
that sets just these first 3 pins here
that we're using as outputs and there's
still another 5 pins here that are part
of Port a that we're not using and we
could configure them as either input or
output and because I left those bits as
zeros in the data Direction register I'm
leaving them as inputs not outputs but
you know we're not using them right now
so it doesn't really matter that we're
leaving just as inputs but anyway now
we've got all these pins hooked up and
we've got them all configured as outputs
we can start sending instructions and
data to the display and if we look back
at the data sheet we can see all of the
different instructions we've got so like
clear display return home entry mode
said and so on and of course all these
instructions have the register select
signals set to 0 because that you know
that's how we tell it that we're sending
it an instruction
you know if register select or 1 then
we'd be actually sending data to the
display but register select zeros for
instructions and then of course the the
read signal here is also 0 for all these
instructions because we're writing to
the display when we send it instructions
and then the instruction itself is kind
of encoded here based on where the first
one is in the data as all of these
instructions start with some number of
zeros followed by a 1 and so if it's if
it's seven zeroes followed by one well
that's the clear display instruction you
know if it's you know four zeros
followed by a one then that's the
display on/off control instruction and
so you can see like the earlier that the
the one appears in the instruction the
more room there is after it for
parameters that kind of go along with
that instruction so the the clear
display instruction for example that's
all one there that's you know that's all
zeros with with a one at the at the very
last position so there's no room for
extra parameters which is fine because
for a clear display there really isn't
any parameter you just you do a clear
display and it clears the display it's
not that complicated but for like the
display on-off control there's four
zeros followed by one and then there's
room for three parameters so there's a
bit here that can be a zero or one
depending on whether you want the
display on or off then there's a bit for
whether you want the cursor display on
or off and then there's another bit for
whether you want the cursor to be
blinking and so you can actually set all
three of those as part of the display on
often
struction but what instructions we
actually descend to get the display to
work well if you flip a little bit
further back in the instructions here or
in the datasheet here I should say they
give some examples and so it's probably
easiest just to find an example that
seems kind of close to what we're trying
to do and then try to figure it out from
there and so this example here is for
8-bit operation which is which is what
we're doing and then it's an eight digit
by two line display and of course we've
got a 16 digit by two line display but I
don't think it's actually gonna make
that much of a difference and this is
sort of the closest example that's in
here but either way you know I'll walk
through the example and actually try to
understand what everything's doing in
here rather than just kind of blindly
following the example and hoping for the
best so you know let's start here with
with step one so step one is is just
powering it on and then it's initialized
no display well we've gotten that far so
step one is a success and then step two
here is function set so it says it's
setting it to 8-bit operation and it's
selecting a two line display with a five
by eight dot character font and so for
this instruction we've got register
select a zero and we're writing so those
those two zeros means you know this is
an instruction and then the the last
eight bits here are that are the actual
data that we're gonna send to to send
the instruction and so the zero zero one
that's sort of the first part up to that
first one that actually tells us what
instruction it is so zero zero one is
the is the instruction and then we've
got the parameters here have one one
zero and then the last two bits that
says it doesn't care so we flip back we
can actually find that instruction in
that table we're looking at before so
it's an instruction here with zero zero
one is the instruction so that's that's
what we were just looking at and then it
says we've got these three parameters
that we can set so DL is the data length
and is the number of display lines and
then F is the character font so we can
see over here on the next page DL if we
set it to 1 that means we're using an
8-bit mode and if DL is zero we're using
4-bit mode so we're using 8-bit mode so
we want to set that to 1 and is the
number of lines on the display so if we
set that to a 1 we've got two lines if
we set that to a zero it's one line and
then the font is either 5 by 10 dots per
character or 5 by 8 dots so that's just
how many pixels make up each character
and you know we really don't have a
choice here either with a number of
lines or the number of dots because the
the physical
display we're using has five by eight
dots for each character so it would you
know it would look wrong if we tried to
use this five by ten so to go back to
the example say zero zero one is the
instruction and then we're setting 8-bit
mode a two line display which is what
we've got and a five by eight character
font which which is also what we've got
so that all sounds like what we want so
let's send this instruction to the
display so again the instruction itself
is zero zero one and then we're gonna
have a one because we want eight bit
mode and then a one for the two line
display and then a zero for the font
which we want the five by eight font and
then the last two bits aren't used so
I'll just set those two zeros because
this doesn't matter and so this is the
instruction to set 8-bit mode to line
display and a five by eight font so I'll
I'll put that in there and then we can
put this out on port B and so that sets
these these 8 data bits out on on port B
here but we also need to set the
register select bit is 0 and the read
write signal as a 0 and those are over
here on port a so we need to make sure
we set those as well so we just load and
store a 0 to port a that'll clear the
register select the read write and the
enable bits and then to toggle some of
these bits what I can do is going to
find some more symbols here for each of
the control signals so the naval signal
is the top bit on port a and then the
read write signal is the next bit and
then register select is the third bit
like this so if we go back down here and
take a look at what we've got so far
we're putting our instruction on port B
here and then we're clearing all of the
the control signals and so in order to
actually send the instruction we need to
toggle the enable bit so what I can do
is load just the enable bit into the a
register and then store that into port a
and so that'll turn the the enable
signal on and then if we immediately set
it back to 0 that'll turn it off again
so this effectively will just toggle
that enable signal on and off really
quickly which will have the effect of
telling the display to then accept this
instruction that is that is sitting on
the data pins so effectively all of this
ends up sending this instruction to set
the 8-bit mode to line display five by
eight font
and of course this here is where we're
setting the enable bit to actually send
the instruction so all of that is just
for this step two here in the
initialization example we've got so that
sets the function so we've got our
display setting this in this mode so
then the next thing in the example here
is the display on or off control so
again this is sending an instruction in
this case it's zero zero zero zero one
so four zeros and a one is the
instruction and then there's three
parameter bits here so if we go flip
back and look at the instructions we've
got from what is it four zeros in a one
that's gonna be display on/off control
so four zeros and a one is the
instruction code there and then the
parameters we have or do we want the
display on or off do we want the cursor
on or off and do we want the cursor to
be blinking or not and if we go back and
look at the example in their case what
they're saying is they want let's see
the display to be on makes sense the
cursor to be on which you know it's up
to us and whether we want to see that or
not and then cursor blinking is off and
that all sounds fine to me so let's
let's send this command and so what I'm
going to do is actually just copy what
we've got here so all of this sent the
first command so I'm going to copy that
and then paste it down here so I've got
a second copy of that except here the
instruction is going to be four zeros
followed by a one so this is the
instruction and then the three last bits
here set the different things so we want
display on cursor on blink off so we'll
said that is a zero so this is gonna be
display on cursor on blink off and we're
sending that to port B that's our data
lines and then same thing here we're
starting with zero on port a and then
we're toggling that enable bit to send
the instruction and so now that should
take care of step three here so we've
got our display turned on our cursor on
and it's not blinking so then step four
is entry mode set and so here again
we've got register select zero read
write is zero and then the instruction
is going to be see one two three four
five zeros followed by a one that's the
instruction and then there's two bits
here at the end of the word we can set
parameters and it says this is setting
the mode to increment the address by one
and shift the cursor to the right
at the time of writing to the display
data or character generator Ram display
is not shifted so what does all that
mean so let's look at what this
instruction is so it's what is it five
zeros followed by one as the instruction
and there's two parameters so if we flip
back here to the instructions table
that's this cursor a display shift so
again we see nope that's not it
entry mode set so we see five zeros
followed by a one so that's the
instruction itself and then there's a
bit for ID and then there is a bit for s
so what are those so it sets the cursor
move direction and specifies display
shift and it's performed during data
write and read so what does all that
mean so ID is well increment or
decrement
so what are we incrementing or
decrementing well understand what this
is doing we've got to look back at the
block diagram I think it's helpful to
look at the block diagram here so
remember we're talking to this interface
through through the the eight data lines
plus these three control signals and so
far we've just been sending instructions
in here and those instructions go into
the instruction register and there's
some decoder and there's some logic that
deals with all that but eventually we're
gonna be sending data to this thing and
actually displaying stuff on the screen
and so when we send that data that goes
into this data register and then
ultimately gets transferred into the
display data Ram and this display data
Ram it's got 80 bytes essentially so it
can hold up to 80 characters of stuff
that's gonna end up displayed on the
screen and so if this has got 80
characters of storage space in it and
there's you know potentially up to 80
characters on the on the screen
depending on what how its hooked up in
our case there's only 32 characters on
our screen but that's just the hardware
we've got but at any event if there's if
there's potentially 80 bytes of data in
here and we only have one byte where
we're sending data to it how does it
know where to put that byte in memory
and therefore how does it know where to
put that character that we're sending on
the screen well to do that it's got an
address counter and so effectively when
we when we reset this thing you know the
address counter is going to say you know
the next character you send is going to
go in the top-left position on the
screen it's gonna go in that first
character and so when we send a
character it's going to put it in RAM in
the right place so that it will appear
first on the display then if we send it
another character what we'd like to do
is have that character then go to the
neck
position on the display and then if we
send a third character that should go to
the third position on the display and so
each character we send just shows up in
the next position on the screen so we
can just type out text and in order for
that to work what we want is that every
time we write a character this address
counter that keeps track of where that
character is going to go on the screen
we want that address counter to
increment each time we write a character
and that's actually what we're setting
with this next instruction so if I can
find the page where we had those
instructions here we go entry mode is is
when we enter data into it what what
mode is it in what is it doing
so this increment or decrement says do
we want to increment that address
register each time we send a character
or do we want to decrement it as
essentially what that saying is like
when we write a character here do we
want the next character to be written to
the right of it or do we want to be
writing backwards so if we have this as
decrement then each time we wrote a
character it would it would decrement
the address counter and the next
character would then go to the left of
the previous character so it seems like
the the normal scenario there would be
you know we want characters to go you
know left to right so we want that to be
incrementing and then s is what was that
that was accompanies display shift which
I believe what that means is that you
can have the the entire display shift
over and so even though you're
incrementing the the address where
you're putting the next character the
screen the entire screen can shift the
other direction which might make sense
if you get to the end of the display and
you want it to scroll but in our case
the example that they have here they're
setting it to increment and they're
setting it to not scroll and so that
sounds like it makes sense to me so
again we want to send another
instruction so what I'll do is I'll just
copy all of this code again to send
another instruction and in this case the
entry mode is five zeroes followed by a
one and then we have two parameters one
is we want to increment the address
register each time we write a character
so that the next character goes that we
send goes next to it and then we don't
want the display to scroll and so we're
incrementing and shifting the cursor
each time but we're not shifting the
entire display okay so now all of this
sends since that instruction is that
step four in this example here and so
the next step by step five is actually
writing data to the data display RAM
which looks like it should actually put
a character on the screen so in this
case one thing that's different is the
register select is now one because we're
not
sending instructions anymore we're
actually sending data so that's that's
the other register so we want to set
register select two one and then we're
still writing so the readwrite signal is
still zero and then the data here this
is actually just the binary
representation of letter H so let's do
this so now the data we want to put out
there is that is that letter H so we
could do the the binary representation
of H like this but instead what we can
actually do is just put the letter H
like that and that's going to do the
same thing because the assembler is
going to know that H is represented as
that particular binary sequence in ASCII
so we can put that H then in Port B and
then just like before we need to
actually toggle that enable signal so
I'll copy that code down here so we're
loading the H and then we're toggling
enable but but we also need the register
select signal to be a 1 because we're
sending data we're not sending an
instruction and so here we want register
select to be a 1 before and after we
toggle enable but also when we toggle
the enable we also need the register
select to be to be a 1 so what we can do
so we can say register select bitwise or
with the enable and that'll basically
set both of those bits so here we have
just the register select bit set here we
have the register select bit and the
enable bit set and then here we have
just a register select bit set so this
will keep the register select bits set
and toggle the enable on or off which
will send the data on port B to the data
register so it should send this H now to
the display and so that's everything
we've got here up to this point where
we're putting a character on the screen
and says you know we can basically
continue to do that to continue to write
other characters to the screen but let's
just try this out and see if that works
so far so at this point in our code once
we've written that H to the screen I'm
actually don't really want to do
anything in the loop so if I just have a
loop and then jump to loop this will
essentially just halt the program
because it'll just throw it into an
infinite loop so once it's once it gets
to this point where it puts the H on the
screen it'll just sit here and loop
forever and not do anything else either
good or bad so let's save that and then
I'll go over and assemble it and I'm
going to use vaz 'm and we want to
create a binary file and we're using dot
directives and then the file is hello
world dot s
and so there we go that compiles it so
if we want we can take a look at the
contents of that binary file that it
created and I guess if you wanted you
could check in and see that it did
everything right looks like it's you
know doing a load AFF and then a store a
two six zero zero two and you could pick
this all apart if you really wanted to
one thing that sort of jumps out to me
is I see the H therefore the actual H
that we're gonna display on the screen
so that that appears in there let's go
ahead and get this put on the EEPROM so
I'll pull the EEPROM addy here put that
in the programmer and we've got an
eighty twenty eight C 256 is the EEPROM
we've got and we're gonna write the a
dot out file and there it goes it's
written and there it goes and so now
we'll stick this back in the circuit and
let's power this up reset it and we have
a cursor and an H hey it worked so were
able to print something to the screen
and it's this code here that's it's
actually printing that H so that's this
block of code here we're putting the H
out on the data port and then we're
actually the comments wrong here we're
setting register select because it's the
you know setting that register select
tells it that we're sending data we're
not sending an instruction and then we
toggle the enable bid on to actually
send the instruction and then here we
are basically just clearing clearing the
enable bit so if all of this works to
send the character each the the quick
and dirty way of sending more characters
would be just to copy this code and add
more letters so if I wanted to print the
message helloworld you know might not be
the cleanest way or the most efficient
way to do it but I could just copy this
block of code for each letter and send
each letter just like like we are here
so that's what I'm actually doing here
and I realized this is not the most
efficient way of writing code but but
that's ok because I just want to get
this working and then we can talk about
how do we actually make this more
efficient or make the code easier to
read right or things like that so there
we go and definitely not proud of this
code but let me make sure I actually
spelled this right but here's here we're
printing hello world definitely using a
lot of code to do it but it should work
so let's let's give this a try I'll save
this and then
go ahead and reassemble it and here
actually if I do a hex dump you'll see
this is this is what I'm talking about
by not being particularly efficient this
is all of the binary code for that
program and it's huge relative to you
know what it's doing just printing hello
world you can see the the message is in
there but that's fine at this point I
just want to get this working and then
we can talk about how to make it more
efficient so let's reprogram it I'll
pull the EEPROM out of here and put it
back in the programmer and then go ahead
and program it there it goes
let's now put the EEPROM back in our
circuit here and power it up and I'll
hit reset and there it goes it's
printing hello world just like we just
like we expected but you know I have to
say I'm not particularly proud of this
code it's a 177 lines of code just to
print the hello world message and it
compiles to 333 bytes of machine
language code just to print the hello
world message I think we can do a lot
better than that and that's what I'm
gonna do in the next video is you know
rewrite this to be a lot more efficient
but I'm gonna do that in the next video
since we're actually going to need to
add some more hardware in order for us
to write more efficient software so
that's when we get into in the next
video and remember if you're interested
in following along with these videos you
can get all the parts I'm using over at
my website Eater dotnet slash 6502 i've
got the base computer kit as well as
everything else you need to follow along
with these videos so you can check that
out at either net slash 6502 and of
course as always i want to thank all my
patrons your support is a huge part of
what makes these videos possible so
thank you
you