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

Embedded Systems, 6502 breadboard computer · Lecture 16 of 29 · 32:59

SPI: The Serial Peripheral Interface

SPI: The serial peripheral interface on YouTube

Study guide

What this lecture covers

Many chip-to-chip communications, such as reading a sensor or writing to a display, don't need the speed or complexity of interfaces like PCIe or SATA. This lecture asks how SPI (Serial Peripheral Interface), one of the simplest and most common of these lighter-weight protocols, actually moves bits between a controller and a peripheral, and how to implement it in software on the 6502 breadboard computer with no dedicated SPI hardware.

By the end, you'll understand SPI's four signal lines and naming conventions, why the protocol has no single standard for clock polarity and phase, how chip select allows multiple devices to share a bus, and how to bit-bang an SPI driver in assembly to read real temperature data from a BME280 sensor.

Key ideas

  • Controller and peripheral (master/slave): SPI is asymmetric; the controller always generates the clock and dictates the communication, while the peripheral only responds.
  • Four signals: clock, chip select (active low), and two data lines, one per direction, commonly called MOSI (master out, slave in) and MISO (master in, slave out); some devices only implement MOSI if they never send data back.
  • No formal standard: pin naming (SDI/SDO vs MOSI/MISO) and clock behavior (mode 0-3, defined by clock polarity and phase) vary by device, so the specific chip's datasheet always determines exact behavior.
  • Simultaneous bidirectional transfer: on every clock edge, the controller both sends a bit out and can receive a bit back, even if one direction's data is meaningless for a given operation.
  • Chip select for bus sharing: multiple SPI devices can share clock, MOSI and MISO lines, distinguished only by separate chip-select lines, optionally driven through a decoder chip to support many devices from few controller pins.
  • Device-specific register protocol: SPI itself only defines the electrical signaling; the actual meaning of the bits (e.g. a read/write bit followed by a register address) is defined per device, as shown with the BME280 sensor's read/write-plus-address scheme.
  • Bit banging: without dedicated shift-register hardware, the 6502 toggles chip select, clock and MOSI directly through I/O port writes to manually clock bits in and out, first the slow way and then via a looped subroutine.
  • Calibration and compensation: raw sensor register values aren't directly meaningful; the datasheet's compensation formula (using calibration constants stored in other registers) converts raw temperature bits into a usable measurement.

Walkthrough

Introduction to SPI (0:00)

The lecture introduces SPI as a simple protocol for chip-to-chip and peripheral communication, contrasting it with more complex serial interfaces like PCIe, and previews the BME280 temperature/humidity/pressure sensor used later.

SPI signal overview and naming conventions (1:00 and 2:40)

The four SPI wires (clock, chip select, and two data lines) are explained along with the SDI/SDO and MOSI/MISO naming conventions, noting that MOSI/MISO has the advantage of meaning the same thing on both ends of the connection.

Three-wire operation and bidirectional data transfer (4:40 and 5:34)

Some devices, like an LED display used only for output, omit MISO entirely. The lecture explains that every clock pulse can carry a bit in both directions simultaneously, even when only one direction's data actually matters.

Clock polarity and phase (7:00)

Because SPI has no formal standard, clock behavior varies: the clock can idle high or low, and data can be sampled on the rising or falling edge, giving four possible "modes" that must be checked against a specific device's datasheet.

Connecting multiple devices (8:53)

Multiple SPI peripherals can share clock, MOSI and MISO lines while each gets its own chip-select line; a decoder chip like the 74LS138 can drive many chip-select lines from just a few controller pins.

The BME280 sensor protocol and register read/write (12:57)

The sensor's datasheet defines a register-based protocol: a read/write bit followed by a 7-bit register address, then either data to write or clock pulses to read back a value, with auto-incrementing reads letting multiple consecutive registers be read in one transaction.

Hardware setup and bit banging (15:34)

The sensor is wired to the 6522 VIA's I/O pins through a 5V-to-3.3V level-shifting board. The first software approach bit-bangs each individual clock and data transition by writing to port A, sending the chip ID register address (D0) and reading back the expected reply (60).

Debugging with the oscilloscope (17:17)

An oscilloscope with SPI protocol decoding confirms the exact bit sequence sent and received, showing the D0 request and the correct 60 chip ID response, while also illustrating that unused simultaneous data (like receiving FF while sending an address) has no meaning.

Optimized software implementation with a transceive loop (23:40)

A reusable transceive subroutine replaces manual bit-by-bit code, looping 8 times to shift a byte out via MOSI while simultaneously shifting a byte in from MISO, used to write configuration registers and read temperature registers.

Reading sensor data and calibration (27:10)

The temperature register bytes are read and displayed as a raw, uncalibrated number that visibly responds to warming and cooling. The lecture then applies the datasheet's compensation formula, using calibration constants stored in other registers, translated into 6502 assembly, to produce a temperature reading in real-world units.

Verifying against a multimeter and closing (30:36)

The computed temperature is compared against a multimeter with a thermocouple probe and found to be reasonably close, confirming the SPI driver, register reads and calibration math all work correctly together.

Before you watch

  • Be comfortable with reading and writing 6502 I/O ports through the 6522 VIA, since this lecture manipulates individual pins directly rather than through dedicated SPI hardware.
  • Familiarity with basic digital signal concepts (clock edges, active-low signals) helps when following the bit-banging timing discussion.

Check your understanding

  1. Why is SPI described as asymmetric, and what role does the controller play that the peripheral doesn't?
  2. What is chip select for, and how does it let multiple SPI devices share the same clock and data lines?
  3. Why can SPI transfer data in both directions on the same clock pulse, and when might that simultaneous data have no meaning?
  4. What information does the BME280's SPI protocol send in its first byte of a transaction, and what determines whether the following bytes are read or written?
  5. Why does the raw value read from the temperature register need to be run through a compensation formula before it means anything in real-world units?

Chapters

From the YouTube description

More 6502 computer info: https://eater.net/6502
Here's the temperature sensor module used in this video: https://www.amazon.com/gp/product/B07P4CWGGK
More info on the sensor: https://tiny.cc/bme280

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:
Aleksey Smolenchuk, Anders Carlsson, Andrew C. Young, Anson VanDoren, Anthanasius, anula, Armin Brauns, Ben, Ben Cochran, Ben Kamens, Ben Williams, Benny Olsson, Bill Cooksey, Binh Tran, Bouke Groenescheij, Bradley Pirtle, Bradley Stach, Brian T Hoover, Bryan Brickman, Burt Humburg, Carlos Ambrozak, Chris, Christian Carter, Christopher Blackmon, Dale Andrew Darling, Daniel Jeppsson, Daniel Tang, Dave Burley, Dave Walter, David Brown, David Clark, David Cox, David Dawkins, David House, David Sastre Medina, David Turner, David Worsham, Dean Bevan, Dean Winger, Dilip Gowda, Dissy, dko, Dmitry Guyvoronsky, Dušan Dželebdžić, Dzevad Trumic, Emilio Mendoza, Eric Dynowski, Erik Broeders, Eugene Bulkin, Evan Thayer, Eveli László, George Miroshnykov, Gonzalo Diaz, Harry McDow, hotwire33, Ingo Eble, Ivan Sorokin, James Capuder, james schaefer, Jared Dziedzic, Jason DeStefano, Jason Specland, JavaXP, Jaxon Ketterman, Jay Binks, Jayne Gabriele, Jeremy, Jeremy Cole, Jesse Miller, Jim Kelly, Jim Knowler, Jim Van Meggelen, Joe Beda, Joe OConnor, Joe Pregracke, Joel Miller, John Fenwick, John Hamberger jn., John Meade, Jon Dugan, Joseph Portaro, Joshua King, Jurģis Brigmanis, Kai Wells, Kefen, Kenneth Christensen, Kitick, Koreo, Lambda GPU Workstations, Larry, László Bácsi, Lucky Resistor, Lukasz Pacholik, Marcos Fujisawa, Marcus Classon, Mark Day, Marko Clemente, Martin Noble, Martin Roth, Mats Fredriksson, Matt Krueger, Matthäus Pawelczyk, Matthew Duphily, Max Gawletta, Maxim Hansen, melvin2001, Michael Tedder, Michael Timbrook, Michael Weitman, Miguel Ríos, mikebad, Mikel Lindsaar, Miles Macchiaroli, Muqeet Mujahid, My Yiddishe Mama, Nicholas Counts, Nicholas Moresco, Not Yet Wise, Örn Arnarson, Paul Pluzhnikov, Paul Randal, Pete Dietl, Phil Dennis, Philip Hofstetter, Phillip Glau, PixelSergey, Porus, ProgrammerDor, Randal Masutani, Randy True, raoulvp, Renaldas Zioma, Ric King, Richard Ertel, Rick Hennigan, Robert Comyn, Robert Diaz, Robey Pointer, Roland Bobek,§çīŤøşHï ŇåĶąýŐbŕÔ, Scott Holmes, Sean Patrick O’Brien, Sergey Kruk, Shelton, SonOfSofaman, Stefan Nesinger, Stefanus Du Toit, Stephen, Stephen Kovalcik, Stephen Riley, Stephen Smithstone, Steve Jones, Tayler Porter, TheWebMachine, Thomas Bruggink, Thomas Eriksen, Tim Walkowski, Tom, Tom Yedwab, Tommaso Palmieri, Tyler Latham, Vincent Bernat, Walter Montalvo, Warren Miller, William, Wim Coekaerts, Wraithan McCarroll, xisente, Yee Lam Wan

← Keyboard Interface Software: From Scan Codes to Characters · Lecture 17: How Hardware Timers Work →