Summary

A 16×2 LCD controller built entirely from multiplexers and logic gates — no microcontroller, no firmware. This project demonstrates how 8 multiplexers (4:1) can be configured as a ROM to execute a complete LCD initialization sequence and later allow user input in ASCII through simple pushbuttons. It is a working proof that digital logic alone can replicate the core functions of a microcontroller.


Inspiration

Every tutorial on LCDs starts with an Arduino. But what if you removed it — completely?

That question led me to an unusual challenge: build a self-contained LCD controller without using any programmable device. The idea evolved through several experimental phases — from random number generators and asynchronous counters to the creation of a custom instruction memory made entirely of multiplexers.

The result: a logic-based LCD driver that initializes the display automatically and then allows users to type any ASCII character through a hardware keyboard.


How It Works

1. System Overview

The project is divided into six functional blocks:

Subsystem Function
Clock Generator (NE555) Produces pulses for synchronization.
Instruction Memory (8×MUX 4:1) Acts as ROM to send 4 preprogrammed LCD instructions.
Control Unit (Counters + Logic) Sequences the instructions and switches to manual mode.
Keyboard Interface (Pushbuttons + Logic) Allows user to input ASCII data manually.
Display Driver (Logic OR + LCD) Routes either automatic or user data to the LCD.
Power & Brightness Control (MOSFETs) Regulates contrast and backlight with pushbuttons.

2. Instruction Memory (Abusing Multiplexers)

At the heart of the project lies a memory made from 8 multiplexers 4:1 (74LS153). Each multiplexer stores one bit of a 4-word ROM. Two control lines (S<sub>0</sub>, S<sub>1</sub>) select which instruction is active:

S1 S0 D7 D6 D5 D4 D3 D2 D1 D0 Instruction
0 0 0 0 1 1 0 0 0 0 Configure 8-bit mode
0 1 0 0 1 1 1 0 0 0 Enable 2 lines
1 0 0 0 0 0 1 1 1 1 Show cursor
1 1 0 0 0 0 0 0 0 1 Clear display

Each combination of (S<sub>1</sub>, S<sub>0</sub>) triggers a unique 8-bit word that the LCD interprets as a valid command. This structure transforms the MUXes into a hardware ROM.

3. Control Logic (Sequencing the Memory)

The sequence through the four instructions is handled by a 4-bit binary counter (74LS193). The counter cycles through 00 → 01 → 10 → 11, feeding the selection inputs of all MUXes simultaneously. When the counter finishes the sequence, a control signal EN switches the system into user mode.

Truth Table for Memory Sequencing

Time (t) S1 S0 EN (Active) Description
0001Send first instruction
1011Send second instruction
2101Send third instruction
3111Send fourth instruction
40Stop automatic mode

Once EN = 0, the control is transferred to the keyboard circuit.

4. Keyboard Interface (ASCII Entry)

The keyboard consists of pushbuttons representing binary bits (D0–D7) and an ENTER key. The user sets the desired 8-bit ASCII code manually and presses ENTER to send it to the display.

Example: To send the character ‘8’ (ASCII 56, binary 0111000):

D7D6D5D4D3D2D1D0
01110000

Pressing ENTER triggers a short pulse equivalent to the LCD “Enable” command.

5. Dual Data Input

A logic OR gate merges signals from both the automatic memory and the user keyboard. During initialization, only the ROM is active. Once setup is complete, the MUX memory is disabled, allowing user inputs to flow freely into the LCD pins.

This transition mimics the firmware “setup() → loop()” structure found in microcontrollers — but achieved with nothing but hardware.

6. Power, Brightness, and Contrast Control

To make the system self-contained, a custom voltage regulator and brightness/contrast controller were built using MOSFETs and pushbuttons. Each MOSFET acts as a variable resistor controlled through small pulses, adjusting the current through the LCD backlight or VO pin.

ControlFunctionElement
Bright+ / Bright−Backlight regulationIRFZ44N
Contrast+ / Contrast−Adjust display contrastIRFZ44N
Power SwitchMain supply controlTransformer 12 V → Regulators 5 V, 12 V

This adds autonomy and a clean aesthetic — no Arduino, no external PSU modules.


Truth Tables and Timing

Memory Operation (Example MUX)

S1S0Output
00C0
01C1
10C2
11C3

This behavior is exploited to map instruction bytes, effectively turning address lines into program counters.

Timing Sequence

t0 – Power ON → Counter Reset
t1 – ROM[0] executes (LCD Function Set)
t2 – ROM[1] executes (Enable Lines)
t3 – ROM[2] executes (Cursor On)
t4 – ROM[3] executes (Clear Display)
t5 – Switch to manual mode
t6+ – User inputs ASCII data manually

This timeline was validated both in simulation (Tinkercad / Proteus) and in physical hardware.


What Makes It Special

This design redefines how we think of “code”: here, logic gates are the program.


Lessons Learned


Future Improvements


Technical Summary

ComponentDescriptionQty
74LS153Dual 4:1 Multiplexer8
74LS1934-bit Up/Down Counter2
74LS2738-bit Register1
NE555Clock Pulse Generator1
IRFZ44NMOSFET Brightness/Contrast Control2
LCD 16×2Output Device1
PushbuttonsASCII Input12
Logic Gates (AND, OR, NOT)Control SignalsVarious

Conclusion

The μMUX Display Controller proves that programmable behavior can emerge from non-programmable components. By pushing multiplexers beyond their intended use, I built a functional, fully automatic LCD driver that bridges the gap between digital logic and computation — without writing a single line of code.

It’s not just a circuit. It’s an homage to the essence of computation — where logic itself becomes language.

— Jesús Ángel Martínez Mendoza