← Sunil Khorwal

Building a Custom GSM Phone: SIM800L, Custom PCB, and No Shortcuts

Published on May 2, 2026  ·  Hardware, Embedded Systems, PCB Design, GSM

I wanted to build a phone the same way people built them before Apple made it a religion — with components I understand, firmware I wrote, and a PCB I laid out myself. No Android, no proprietary stack. Just a microcontroller, a SIM module, an LCD, and a keypad. The goal: make and receive real calls and SMS on a 2G network.


The SIM800L — Power Gotcha First

The SIM800L is a quad-band GSM/GPRS module that communicates via UART using standard AT commands. Every tutorial online shows it wired to a 3.3V regulator and then wonders why it randomly resets mid-call. The reason: during a GSM transmission burst, the SIM800L can spike to 2A of current draw for milliseconds. A standard AMS1117 or LM3940 linear regulator can't sustain that.

I learned this the hard way. My first prototype with a linear regulator would drop calls the moment it tried to register on the network. Scoping the supply rail showed voltage dipping to under 3.0V during RACH bursts. The fix was a dedicated LM2596 buck converter with a 470µF low-ESR capacitor on the output, sized to handle those transient current spikes without rail sag.

Power supply requirements for SIM800L
Operating voltage : 3.4V – 4.4V (3.8V optimal) Peak current : 2A (during TX burst, ~577µs) Standby current : ~1mA Sleep current : ~0.7mA → Use LM2596 or equivalent buck, NOT a linear regulator → Add 470µF electrolytic + 100nF ceramic at the module supply pins

AT Command Protocol — Talking to the Network

Once powered correctly, the SIM800L communicates over UART at 9600 baud by default. Every operation is a request-response cycle over AT commands. The tricky part isn't sending a command — it's handling the unsolicited result codes (URCs) the module sends asynchronously. An incoming call doesn't wait for you to poll; the module just interrupts with RING on the serial line.

Key AT command sequences
// Check registration AT+CREG? +CREG: 0,1 ← registered on home network // Make a call ATD+911234567890; OK ... (call connects) ATH ← hang up // Send SMS (text mode) AT+CMGF=1 OK AT+CMGS="+911234567890" > Hello from my custom phone! (Ctrl+Z to send) +CMGS: 42 OK // Incoming SMS notification (URC, comes any time) +CMTI: "SM",3 ← new SMS at index 3 in SIM storage AT+CMGR=3 ← read it

Firmware: The Non-Blocking UART State Machine

The core firmware challenge is this: the keypad input, the LCD refresh, and the SIM800L serial buffer all need attention simultaneously. A blocking waitForResponse() call would freeze the UI while waiting for the network. The solution is a non-blocking state machine that processes one character at a time from the UART RX ring buffer per main loop iteration.

Simplified UART state machine logic
typedef enum { STATE_IDLE, STATE_RINGING, STATE_IN_CALL, STATE_SMS_INCOMING, } PhoneState; void loop() { if (uart_available()) { char c = uart_read(); buffer_append(c); if (buffer_contains("RING")) state = STATE_RINGING; if (buffer_contains("+CMTI")) state = STATE_SMS_INCOMING; if (buffer_contains("NO CARRIER")) state = STATE_IDLE; } handle_keypad(); // always responsive update_lcd(); // always refreshing }

This means the phone is always responsive to button presses, even mid-network operation. The RING string in the buffer triggers the display to show the incoming call screen, while ATA\r is queued to be sent on the next answer key press.


The PCB — From Breadboard Chaos to a Real Board

The breadboard prototype worked but was fragile — RF signals don't like long jumper wires, and the SIM800L antenna trace especially needs controlled impedance. Moving to a custom PCB solved this. Key design decisions:


The Result

The device makes and receives calls, sends and receives SMS messages, and runs on a 1000mAh Li-Po battery. It's slower than a modern smartphone by every measure, but every layer of it — from the schematic to the firmware state machine to the PCB copper pour — is something I designed, debugged, and understand fully. That's the point.