Seyed Masoud Hosseini · Overview · Study log · Ideas · Transcript · RSS feed

Embedded Systems, 6502 breadboard computer · Lecture 4 of 29 · 28:10

Part 4: Connecting an LCD to our computer

Connecting an LCD to our computer — 6502 part 4 on YouTube

Study guide

What this lecture covers

This lecture connects a standard 16x2 character LCD module to the breadboard computer and walks through the low-level protocol needed to control it: the data lines, the register-select and read/write control signals, and the enable pulse that actually latches a command or character. It treats the LCD's controller datasheet as the primary reference, working through its instruction-set diagrams example by example.

By the end, the lecture gets the display to print first a single character and then the full "Hello world" message, while being explicit that the resulting assembly code is long and inefficient. That inefficiency sets up the next video's motivation for adding more hardware and writing cleaner software.

Key ideas

  • Register select (RS): chooses whether the LCD's data lines are interpreted as an instruction (RS low) or as data to display (RS high).
  • Enable (E) pulse: toggling the enable line high then low is what actually triggers the LCD to read whatever is currently on the data and control lines.
  • 8-bit vs. 4-bit mode: the LCD supports sending data over 8 lines (simpler, used here) or 4 lines (fewer wires, more complex), configured in the function-set instruction.
  • Function set instruction: an early setup instruction that fixes the interface width, number of display lines, and character font (5x8 dots here) and must match the physical hardware.
  • Entry mode set: configures whether the address counter increments or decrements after each character is written, and whether the whole display shifts, which determines how typed text advances across the screen.
  • Address counter and display data RAM: an internal 80-byte memory holds on-screen characters, with an address counter tracking where the next written character will land.
  • Symbolic addresses and bit constants: naming register addresses (PORTB, DDRB) and control bits (enable, read/write, register select) makes the assembly code far more readable than raw hex.
  • ASCII literals in assembly: the assembler can accept a character like H directly and encode it as its ASCII byte, instead of writing out the binary by hand.

Walkthrough

Wiring power, contrast, and the backlight (0:00)

The LCD's power pins are connected to 5V and ground, and a potentiometer sets the V0 contrast pin. The backlight anode and cathode are tied to power and ground directly, since the module already includes a current-limiting resistor.

Wiring the data and control lines to the VIA (2:02)

All eight data lines are connected to VIA port B (the same pins previously used for LEDs), and the RS, R/W, and enable control signals are connected to three pins on port A. The lecture notes that a 4-bit mode exists to save wiring but sticks with the simpler 8-bit mode.

Reading the LCD controller datasheet (4:02)

The lecture explains that the relevant datasheet is for the LCD's driver chip, not the whole module, and that most of its pins (which drive the physical pixels) can be ignored. It focuses on the microprocessor-facing interface: the eight data lines plus RS, R/W, and E, and explains how RS distinguishes the instruction register from the data register.

Configuring the VIA ports for output (6:04)

The existing assembly program (previously used to blink LEDs) is adapted, using named symbols for PORTA, PORTB, and their data direction registers, and writing binary literals (%11111111) instead of hex to make which pins are configured as outputs more explicit.

Sending the function-set and display-control instructions (10:06)

Following the datasheet's initialization example step by step, the lecture builds and sends the function-set instruction (8-bit mode, two lines, 5x8 font) and the display on/off control instruction (display on, cursor on, blinking off), each time writing the instruction byte to port B, clearing RS and R/W on port A, then pulsing the enable bit.

Setting entry mode and writing the first character (17:16)

The entry-mode-set instruction configures the address counter to increment after each character without shifting the whole display. With RS now set high to indicate data rather than an instruction, the letter H is written to port B and latched with an enable pulse, and the lecture explains how the LCD's internal address counter and 80-byte display RAM place each written character in sequence on the screen.

Assembling, programming, and testing "Hello world" (23:17)

After confirming a single H appears on the display, the lecture copies the same block of code once per letter to print the full message. The resulting program, acknowledged as inefficient at 177 lines and 333 bytes of machine code just to print one string, successfully displays "Hello world" once assembled, written to the EEPROM, and powered on.

Before you watch

  • Watch parts 1 through 3 first, since this video reuses the VIA wiring, port/data-direction setup, and assembler workflow built there.
  • Comfort reading binary and following bit-field diagrams in a datasheet is useful for the instruction-set discussion.

Check your understanding

  1. What does the register select (RS) signal control, and how does its state change between sending an instruction and sending a character?
  2. Why must the enable line be toggled to actually transmit data to the LCD, rather than just placing values on the data lines?
  3. What does the entry mode set instruction configure, and why does the lecture choose to increment the address counter without shifting the display?
  4. Why does the lecture say the "Hello world" program is inefficient, and what does that suggest for the next video?
  5. How does the LCD's internal address counter determine where each newly written character appears on screen?

Chapters

From the YouTube description

Schematics, datasheets, kits, and more at https://eater.net/6502

Part 1: https://www.youtube.com/watch?v=LnzuMJLZRdU
Part 2: https://www.youtube.com/watch?v=yl8vPW5hydQ
Part 3: https://www.youtube.com/watch?v=oO8_2JJV0B4
Part 4: This video!
Part 5: https://www.youtube.com/watch?v=xBjQVxVxOxc
Part 6: https://www.youtube.com/watch?v=i_wrxBdXTgM
Part 7: https://www.youtube.com/watch?v=omI0MrTWiMU

Support these videos on Patreon: https://www.patreon.com/beneater or https://eater.net/support for other ways to support.

------------------

Social media:
Website: https://www.eater.net
Twitter: https://x.com/beneater
Patreon: https://patreon.com/beneater
Reddit: https://www.reddit.com/r/beneater

Special thanks to these supporters for making this video possible:
Adam Lininger
Adrien Friggeri
ahmed
Alex Catchpole
Andrew R. Whalley
Anthony Cuccia
Armin Brauns
Austin Grant
BakerStaunch
Beau-James Erion
Ben Dyson
Ben Kamens
Ben Williams
Bradley Pirtle
Brandon Stranzl
Brian Wanda
Bryan Brickman
Carlos Ambrozak
Chad Fertig
Christopher Blackmon
Chuck Crizer
Clayton Parker Coleman
Daniel Tang
Dave Walter
David Boardman
David H. Friedman
David House
David Turner
Dean Winger
Debilu Krastas
Dominic Kulmer
Dušan Dželebdžić
Dzevad Trumic
Eric Brummer
Eric Busalacchi
Eric Dynowski
Eric Twilegar
Erik Broeders
Eugene Bulkin
Foaly
fxshlein
Gabriel Lafond-Thenaille
HaykH
hunter wright
Ian Tait
Ingo Eble
Ivan Sorokin
Jackson Warren
Jason DeStefano
JavaXP
Jay Binks
Jayne Gabriele
Jeremy A.
Jeremy Wise
Jimmy Campbell
Joel Messerli
Joel Miller
Joern Heidenreich
Jon Dugan
Jordan Scales
Joshua King
Justin Dubs
Justin Duch
Kefen
Kent Collins
Maksym Zavershynskyi
Manne Moquist
Marcus Classon
Mats Fredriksson
Matt Alexander
Matthew Mattox
Matthäus Pawelczyk
Michael
Michael Burke
Michael Garland
Michael Tedder
Miguel Ríos
Mirko Rener
Nathan Wachholz
Nicholas Counts
Nicholas Moresco
Nick Sutton
Nick Wrightsman
Onion Sniffer
Paul Pluzhnikov
Paul Randal
Pedro Madhat
Peter Simard
Philip Hofstetter
Randy True
Ric Allinson
Ric King
Richard Wells
Rob Bruno
Robert Blackshaw
Robert Butler
Ross
Sachin Chitale
Sam Rose
Scott
Sergey Ten
Sever Banesiu
SonOfSofaman
Stefan Nesinger
Stefanus Du Toit
Stephen Riley
Stephen Smithstone
Steve Jones
Steve Gorman
Steven Pequeno
sunyiming
Sylvain Thrd
Thomas Ballinger
Tom Burns
Vladimir Kanazir
Warren Miller
xisente
Örn Arnarson

← Part 3: Assembly language vs. machine code · Part 5: What is a stack and how does it work? →