Is it possible to implement an SPI module such as a LoRa module, eg. RFM95, without the use of a [modern] microcontroller?

Edit: I have a hobby project that’s using a Z80 CPU.

The most available/accessible LoRa module seems to be the RFM95, which I observed always appears to be demonstrated by using a [modern] microcontroller such as Arduino or ESP8266 (because I suppose it’s easier that way).

I understand that this is a difficult question to answer since that module uses SPI (MOSI/MISO) to communicate with microcontrollers.

For context, I want to transmit and receive very simple data—-a simple on/off message to and some very basic sensor data from a remote device—-but want to see if I can do this using LoRa without the need to use a microcontroller (mostly out of curiosity). To elaborate, I want to try not using a [modern] microcontroller, since I find myself leaning on an MCU for almost everything, and I believe the ability to solve everything with code is hindering my ability to learn more optimal hardware solutions.

In other words, do you need a [modern] microcontroller to decode the SPI signal from a LoRa module such as the RFM95, or can this be done using much simpler chips without firmware?

I have experimented with simpler radio technology such as a basic 433MHz module, but the signal is not strong enough for my project (even with a good antenna).

Related: How can SPI be used with a Z80 CPU?

  • \$\begingroup\$ Not reasonably. You would need many (hundreds? more?) discrete logic gates, flip flops, and register chips which just pushes you to an FPGA which could be a useful experience in itself (it's cumbersome enough tp type out the HDL for an FPGA, let alone physically wire it up as discrete logic). There's a reason complex sequential digital operations were quickly pushed to processors and FPGAs as soon as it was feasible. I think you would learn a lot more for not much more effort than building an MCU from discrete components. \$\endgroup\$
    – DKNguyen
    Commented Jul 9, 2022 at 18:49
  • \$\begingroup\$ How about FPGAs? Edit: Ah, just noticed first comment. I think that might be the answer. \$\endgroup\$ Commented Jul 9, 2022 at 19:46
  • \$\begingroup\$ Going without a micro would have been something to consider in the ‘80s but these days a micro costing $1 and a few lines of Arduino code are a no-brainer unless you want to design something as an exercise \$\endgroup\$
    – Frog
    Commented Jul 9, 2022 at 21:52
  • \$\begingroup\$ Just for fun, I want to try without an MCU, but it’s proving difficult. \$\endgroup\$ Commented Jul 9, 2022 at 23:22
  • \$\begingroup\$ FPGA UART-to-SPI Interface - Design Example \$\endgroup\$ Commented Jul 10, 2022 at 0:40

6 Answers 6


You left out important information which your question on Retrocomputing has.

Yes, you can interface a Z80 CPU with a SPI device.

There's plenty of options.

You need an I/O port for the SPI pins and then control the I/O pins in software. This is commonly called bit-banging the bus protocol in software.

Another option is to build some circuitry to convert byte writes on a parallel data bus to a transfer sequence of 8 serial bits and also receive 8 serial bits so they are readable on the bus. It just needs some serial/parallel shift registers and some glue logic to implement it, so while it can achieve faster bit transfers for a whole byte in hardware without software intervention, it takes a lot more effort to implement the hardware.

  • \$\begingroup\$ I actually wasn’t sure how open to retro computing the wider EE community was, now I know! :-) \$\endgroup\$ Commented Jul 9, 2022 at 23:16
  • \$\begingroup\$ Question edited to reflect this. \$\endgroup\$ Commented Jul 9, 2022 at 23:22
  • 3
    \$\begingroup\$ So the question in fact was not how to communicate without MCU to SPI device but with a Z80 CPU to SPI device. \$\endgroup\$
    – Justme
    Commented Jul 9, 2022 at 23:40
  • 2
    \$\begingroup\$ You control SCLK, so slaves run at whatever speed you want. And some of us cut our teeth on Z80's! \$\endgroup\$ Commented Jul 10, 2022 at 1:10

Just for fun: You can use a parallel 8 bit EEPROM or FRAM in combination with a binary counter connected to the lowest address lines. Three of the 8 data lines provide the signals for /CS, CLK and MOSI during counting.

Some high bit address lines can be used to select different messages or measured values. A lot of pulse sequences can be stored in such a memory.


Put a GPIO port on your Z80 (hopefully you know how to do this; it's a separate question).

Then bit-bang the SPI bus. Meaning, generate the clock and output data in software on the processor, and read the input data back the same way.

Note that this will use a lot of CPU resources -- this is why people started building SPI peripherals into microcontrollers fairly early on.

If you're lucky, there may be a (now obsolete) USART chip out there can do synchronous (the "S" in "USART") as well as asynchronous communications. Zilog used to make companion chips for the Z80 including a UART, and IIRC the Zilog memory interface is compatible with the Intel 8080 memory interface -- so as long as you can actually find stock, there may be some part out there that you can use.

  • \$\begingroup\$ You can get an Intel MR8251 from Rochester for most of 100 bucks. Prices on Z80SIO from Quest much nicer. \$\endgroup\$ Commented Jul 11, 2022 at 4:18
  • \$\begingroup\$ @Jasen: 1/10th that from Jameco for a "refurbished" unit. 74HC563's are still available, so everything else you need to decode an address and just implement GPIO is probably there. \$\endgroup\$
    – TimWescott
    Commented Jul 11, 2022 at 15:02

it seems like FPGA might be the only practical alternative to a microcontroller

"Only practical alternative" - what you're doing is hardly "practical". If you wanted practical on a Z80 (for whatever reason), you'd use a modern eZ80. It has a built-in SPI peripheral :) Some years ago you'd have also had the option of using a Rabbit MCU, but those IIRC are gone now.

Alas, I'm sure it's all done just for the heck of it and "why not". Several period-accurate retro options are available for you.


"Bit banging" on a CPU like Z80 would be looked down upon, because that poor CPU is not very fast to begin with, so to waste the precious cycles on major bit-banging likely wouldn't be practical - at least not if application speed was a concern, e.g. when using CP/M and some perhipheral via SPI.


Perhaps you don't care to repurpose an existing synchronous USART, 'cuz it'd be almost like cheating.

Discrete UART

At minimum you'd do an actual I/O-mapped SPI "UART". Basic options are:

  1. Use a handful of TTL or 4000-series logic.

  2. Use a couple PALs - likely two registered ones and a combinatorial one. Or use three GALs.

The "handful of TTLs/4000s" would be a very likely route to go in the late 70s and early 80s. You need a shift register, maybe a couple octal latches for a FIFO if you're so inclined - then also two or three counters to keep state, a clock divider, a bit counter, and some combinatorial logic to make it all work. Without a FIFO you'd want to use good old Z80DMA to keep the data moving.

I believe the ability to solve everything with code is hindering my ability to learn more optimal hardware solutions.

MCUs usually come with SPI peripherals, so you're not solving the SPI problem with code. You're just using code to talk to the SPI peripheral that then talks to the LoRa. Since legacy Z80 has no built-in SPI support, you'd provide it yourself, but it'd be a very application-agnostic thing - just like a UART, except for SPI, not caring much what the data sent/received actually means.

Bus-mapped SPI Peripheral Register Space

Now, if you don't want to use software to deal with SPI transactions, and want a "higher level" solution that would feel more native - and perform better - you'd want to expose the SPI slave's register space directly to I/O port space of the Z80.

To do that, you'd put together a state machine that converts I/O accesses to SPI transactions, and adds any necessary wait states to the bus transactions. SPI on most peripherals runs quite fast compared to legacy Z80 bus speeds, so perhaps no waitstates would be needed - or just one. The software would see the SPI periphera's register space as-if it was a parallel data bus peripheral with address decoding, connected to the bus. So, the LoRa chip would appear more like a UART to the software.

That'd be quite a nifty solution to the problem, and not too impractical with modern design tools. You can design a much tighter through-hole 2-layer PCB today than in the 80s - and get it manufactured for coffee money. You can even (OMG!) have several prototypes made over a period of weeks, iterating quickly to get all the bodge wires off the board. In the 80s and 90s, you'd have needed deep pockets to afford that, and ideally a PCB manufacturer in the same town.

The "software" the Z80 would need to use this peripheral would probably fit in 128-256 bytes of EPROM. So, very period-appropriate for late 70s. Heck, you probably could fit it in the 74-series bipolar PROMs if you can find some, and someone to program them for you.

Discrete State Machine + "UART"

Once you're ready to ditch the Z80, set up another hardwired logic state machine that will use the bus-mapped SPI "adapter" to provide the equivalent of the application layer.

SPI Playback from Memory

Or, you know, you can just play back bits from a parallel EPROM or PROM when the trigger comes. D0 for MOSI, D1 for SCLK, D2 for ~CS. An external address counter, and an RS FF to stop the counter when it overflows. But that feels almost like cheating: back then memory was expensive, and a CPU with a small PROM with code, plus some discrete glue logic, may have cost less than a large PROM with bit-banged messages.

SPI Playback from Less Memory

MC14500B would be considered a slightly more integrated state-machine building block. A couple ancillary chips and a small (64 byte?) PROM would do it.

SPI Playback with Slightly More Software

An Intel 4004 + one or two 4001s could be used to "approximate" a discrete state machine. Given how simple those chips were, it really isn't anything even remotely like writing Z80 assembly, in terms of the abstraction level. A 4-bit CPU is plenty for bit-banging a fixed short SPI message or a few. 4001s give you some I/O and code/data ROM. A 4004 provides a slightly higher level assembly than MC14500B family, but still close to writing "state machine assembly".

  • \$\begingroup\$ Yeah, "only practical" is definitely wrong. Edited. \$\endgroup\$ Commented Jul 24, 2022 at 22:03

From the comments, it seems like FPGA might be one alternative to a microcontroller for modules that implement SPI or any other serial bus.

  • \$\begingroup\$ A CPLD could do it too, but conceptually we can lump that in the same category of programmable logic. \$\endgroup\$
    – TypeIA
    Commented Jul 9, 2022 at 20:19
  • \$\begingroup\$ " or can this be done using much simpler chips" - its unlikely that the FPGA will be much simpler than a MCU \$\endgroup\$
    – Wesley Lee
    Commented Jul 9, 2022 at 20:42
  • \$\begingroup\$ Good point. So FPGA would not be simpler but would be an interesting learning experience. \$\endgroup\$ Commented Jul 9, 2022 at 21:07

There was once a market for parts that could fill this role - Programmable Array Logic/Generic Array Logic (PAL/GAL) chips. The predecessors to FPGAs, these allowed you to implement a fair number of arbitrary logic gates with optional registers. Unlike FPGAs, it was feasible to program them with pencil, paper, and a hex editor - draw your circuit, use boolean algebra to simplify the circuit, program the "fuses" in the device accordingly. Digital bus operations were well within their purview as you really don't need that many gates to implement a few basic operations - I've implemented an I2C slave capable of reading out data from an EEPROM, and the two operations (set address on writes, push out data on reads) took five GAL chips IIRC.

However, this market was dashed by the availability of extremely small and power efficient MCUs. It's now more efficient to pop a PIC on a board if you need an operation that would take a few dozen logic gates. GALs are very hard to find nowadays, and are basically legacy hardware used for repairs of old systems.

Nowadays the niche for combinatorial logic smaller than an FPGA is filled by CPLDs (Complex Programmable Logic Devices), so that would be the tree to bark up if you want to try your hand at a gate-level implementation. Make sure you get one that can be programmed with manual gate configuration - synthesizing from HDL is probably a more marketable skill, but doesn't sound like the skill you're looking to try out.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.