# Designing a USB-C LTE modem: a real phone line for my computer and my AI agent

I wanted a real phone line plugged into my computer, with one simple rule:

- **When I'm at my desk,** I read and send texts and answer calls from the computer, with my normal headset.
- **When I'm away, in deep work, or I don't know the number,** my AI agent picks up, talks to the caller and sends me a summary notification.

The usual ways to do this hit two dead ends:

1. **A cloud VoIP number.** You pay every month, all your audio goes through someone else's servers, and many apps and spam filters treat the number as VoIP and not a mobile line.
2. **An old Android phone on a charger.** Android gives you no clean way to get call audio in and out over USB, so you end up with Bluetooth or analog-cable hacks.

What I wanted was a headless board with no battery: a physical nano-SIM goes in, and the computer gets direct control over calls, call audio, SMS and LTE data.

So I wrote a one-page spec and gave it to Koppar, the tool I'm building. It produced the schematic, matched every part to a real distributor listing, routed the 4-layer board and reviewed it against the datasheets.

Then I took it to JLCPCB: five boards, two of them assembled, **$102.61** in the cart. This is the log: how the board works, what I changed, and what it took to get it ready to order. Not one of the problems below was a DRC error.

## One USB-C cable, three devices

The hard part of cellular hardware isn't sending an SMS. It's getting call audio into the computer in both directions, so that a person or a script can take the call.

A USB 2.0 hub (U2) sits right behind the USB-C connector (J1). Plug the board in and the computer sees three ordinary devices:

- **A network adapter:** LTE data straight from the modem, as backup internet.
- **A serial port:** AT commands. The modem reports who is calling (+CLIP), texts go out with AT+CMGS, and ATA answers a call.
- **A USB sound card:** an RP2040 (U5) takes the modem's digital call audio (PCM, at 1.8 V) and shows up to the OS as a microphone and a speaker.

So routing a call is just software. Here's the plan. A call comes in, the amber RING LED (D3) lights and a prompt pops up on the desktop. I click Answer and the call audio goes to my headset. I ignore it for three rings, or I'm in Away mode, and the agent sends ATA and takes the audio stream itself.

The board has no battery, no screen and no speaker. It runs on USB-C bus power and has three status LEDs along the bottom edge: green NET (D2), amber RING (D3) and blue CALL (D5).

![The board I ordered. 85 × 65 mm, 4 layers, 107 parts.](https://cdn.hashnode.com/uploads/covers/640cbe53d7f2743f2a351b85/c8ed2500-f5c0-46c3-a7bd-702a27840838.png align="center")

*The board I'm ordering. 85 × 65 mm, 4 layers, 107 parts.*

## Trap 1: the right module variant

The core of the board (U8) is a Quectel EC25-EUX: European LTE bands, with 3G and 2G fallback. Not every EC25 does voice. The data-only variants (in North America, EC25-AFDL and EC25-AFXD) have no voice. The EUX lists PCM digital audio: PCM_CLK, PCM_SYNC, PCM_DIN and PCM_DOUT. The spec's first draft had the wrong variant, and the review caught it.

The module's logic runs at 1.8 V and the RP2040 and its flash (U6) at 3.3 V, so a level shifter (U7) sits between them. The RP2040's USB lines have 27 Ω series resistors right at its pins, as its datasheet asks.

## Trap 2: 2 A bursts off a USB-C port

When the modem falls back to 2G in weak coverage, each transmit burst draws up to 2 A. If the rail sags below the module's minimum during a burst, the modem resets mid-call. An old 500 mA USB-A port won't do.

- **USB-C input.** Two 5.1 kΩ resistors on CC1 and CC2 mark the board as a USB-C sink, with ESD protection (U1) on the data lines. Those resistors don't negotiate anything: the port decides how much current it offers, so this board wants a port and cable that advertise 3 A at 5 V.
- **3.8 V buck (U3).** It brings 5 V down to 3.795 V, set by a 40.2 kΩ / 10.2 kΩ divider. A separate 3.3 V regulator (U4) feeds the hub, the RP2040 and the flash.
- **Bulk capacitance.** Two 220 µF polymer capacitors (C36, C37) sit at the module's power pins to absorb the bursts.

The review flagged the supply copper at 1.37 mm, below Quectel's 2 mm guidance. On the board I ordered it's widened wherever the clearances allow (1.4 to 2.0 mm), and a solid copper area runs from the bulk capacitors into the four VBAT pins.

## Trap 3: RF, and tuning pads

The two u.FL antenna jacks sit on the top edge: J3 (MAIN) and J4 (DIV). Between each jack and the module there's a pi network: a fitted 0 Ω series resistor with two empty shunt pads. That lets me tune the antenna match on the bench without a new board.

The first version had two RF problems: 0.33 mm feeds (about 35 Ω on this stackup, not 50 Ω) and a main feed that hopped layers through vias. Both are fixed on the board I'm ordering, along with two other things the review found:

![](https://cdn.hashnode.com/uploads/covers/640cbe53d7f2743f2a351b85/a85ad6ef-18a5-4afd-bc10-399030220d79.png align="center")

1. **The buck's switch node.** U3 and its inductor L1 were about 60 mm apart, so a 3 A switching node ran across the board, where it radiates and rings. U3 and its parts now sit under L1, 4.1 mm from pin to pad.
2. **The antenna feeds.** They're now 0.20 mm (49 Ω), on the top layer only, with no vias and with ground stitching along them.
3. **The SIM socket.** Its card slot faced the module, 6 mm inside the board, so no card could ever go in. The socket is turned 180° and the slot sits flush with the edge.

The SIM socket (J2) also has series resistors and ESD protection, so swapping cards by hand doesn't zap the module. I also added 14 test pads for bring-up, and moved 90 vias out of SMD pads. None of them needed to be there, and a via in a pad means paying the fab to fill and cap it.

## The fab boss fight

![](https://cdn.hashnode.com/uploads/covers/640cbe53d7f2743f2a351b85/402d9815-6cf4-43fd-9ed7-0edb172c2c63.png align="center")

**5 PCBs $16.55 + 2 Economic PCBA $86.06 = $102.61**

0 DRC errors and 0 unconnected nets is where ordering starts, not where it ends.

**Held at the first attempt.** Koppar wouldn't release the first version because the SIM supply had too little current margin. It also raised eight review warnings, including the crystal load capacitors. Better to find that before paying for a board.

**The parts list.** Every BOM line came back with a match. Six of the matches would have built a board that doesn't work or doesn't fit:

![](https://cdn.hashnode.com/uploads/covers/640cbe53d7f2743f2a351b85/5d83851d-1f4f-4fd1-bc56-a19db35aa082.png align="center")

The inductor is the one to remember. The footprint named a family (SRP1245A), every member of that family counted as a match, and the first one in stock was 18 µH instead of 4.7 µH. Nothing about that looks wrong in a BOM viewer. Koppar now checks each part's value and body size, and it matches amber LEDs to what the catalogue calls yellow.

**Basic parts.** At JLCPCB, every Extended part adds a loading fee per unique part, and on a board like this they add up fast. I went through the BOM and swapped in Basic parts wherever one fit. That's how 5 boards with 2 assembled came to $102.61.

**Rotations in the DFM preview.** The Gerbers and the placement file agreed with each other, and parts were still placed wrong:

![](https://cdn.hashnode.com/uploads/covers/640cbe53d7f2743f2a351b85/d73a1b19-221b-47d4-97a6-0ec4bc4d9a01.png align="center")

I also checked pin 1 on every IC and the polarity of the two 220 µF capacitors before confirming. Koppar's order files now get these four right, and they flag every diode and polarised capacitor for a look, because no file can settle those for sure.

**Why U8 is empty in the preview.** JLCPCB had no EC25-EUX in stock, and one ordering code is end-of-life. So I'll buy the modules separately and solder the 144-pad LGA myself when the delivery arrives.

## Where it did well, and where it's improving

![](https://cdn.hashnode.com/uploads/covers/640cbe53d7f2743f2a351b85/6341f670-7028-45e8-9af5-83d5142c6ae0.png align="center")

Everything on the right is a real defect that a DRC-clean board shipped with. Each one is now either fixed in Koppar or next on the list. A board that passes DRC still isn't a board that works, and that gap is the job.

## Open files, and what's next

I'm making everything public for anyone to check and improve on:

**The design:** spec, schematic, KiCad 10 project, Gerbers, BOM and placement files, and the review with every number. CERN-OHL-P. Github repo: <https://github.com/Koppar-AI/koppar-lte-modem>

![](https://cdn.hashnode.com/uploads/covers/640cbe53d7f2743f2a351b85/4aa292de-4137-4cad-bb23-7d550e866042.png align="center")

I left the BOOTSEL button off to keep the board minimal, since a blank RP2040 boots into its USB bootloader anyway. Instead, the back has a BOOT pad pair (tweezers across it while plugging in), SWD pads, and the modem's USB_BOOT recovery pads. What else would you have broken out before the first bring-up?

## Try it on your own board

I'm building Koppar on my own for now, and boards like this one are how I test it. Everything on the right of that scorecard is now either a check in Koppar or the next one on my list.

- **Start from a spec.** Describe the board at [koppar.ai](http://koppar.ai), in one sentence or one page. You get the schematic, the routed board, a BOM at live prices, and Gerbers, or a list of what's holding it back. Three free runs.
- **Bring a KiCad board.** You get it back placed and routed with the DRC report, and the files are yours.
- **Work from your agent.** Koppar is an MCP server, so Claude Code or any MCP client can drive it from the spec to the fab files.

When it gets something wrong on your board, tell me on X ([@abijahkaj](https://x.com/abijahkaj)). That's the next thing I fix.
