RotaryOpen sourceNo subscription

Build four phones for you and your friends

Old corded phones, an adapter, a cable to the home router, and one small cloud server. Free calls between your four phones, nothing else. This page walks through it step by step, including how to build the adapter yourself.

Status: a plan, not a tested build. Prices, part names and figures are estimates; check every part and datasheet before ordering. Diagrams on this page are my own drawings, not photos.

1. The big picture

Each friend gets an old corded phone plugged into a small adapter. The adapter plugs into the home router with an Ethernet cable (no Wi-Fi). All four phones connect to one cloud server. The server is the phone book, the switchboard and the audio relay. You dial 101, 102, 103 or 104. Nothing else can be dialed, including 911.

Home A Home B Old corded phone extension 101 Adapter bought ATA, or your own Home router Ethernet port phone cord Ethernet cable Old corded phone extension 102 Adapter bought ATA, or your own Home router Ethernet port Cloud server Asterisk phone book + switchboard audio relay rule: 101 to 104 only calls and audio travel over the internet, through the server
Figure 1. The whole system. Phones 103 and 104 sit in two more homes and connect the same way.

Two ways to do the adapter

Buy an adapter (section 5)Build your own (section 6)
What it isA boxed Grandstream HT801, about $34 to $50An ESP32-S3 board with a phone-line module, about $50 to $75 in parts
Time to a working callA few hoursAbout 4 to 8 weekends if you have embedded experience
Open sourceServer onlyServer, firmware and hardware
RiskLowReal electronics and firmware work, with ring voltage on the line
Recommended orderSet up the server and run four phones on bought adapters first, so your friends can start calling. Build your own adapter on the bench in parallel, and swap it in for one phone when it works.

2. Safety first

These phones cannot call 911.Put this sticker on every phone, and tell each friend in person: "This phone cannot call 911 or any outside number. Use your mobile phone for emergencies." Dialing anything other than 101 to 104 plays a spoken message.
If you build the adapterThe phone-line module supplies a 48 V DC line and rings the phone at about 60 to 65 Vrms (20 to 25 Hz). Keep the build in a closed box, use a certified power adapter, and never touch the phone-line terminals while powered. Check voltages with a meter before connecting a phone.

3. Choosing old phones

Most old analog phones work. A thrift store or eBay is a good source.

TypeWorks?Notes
Corded, push-button (tone dial)YesPlugs straight into the adapter's phone port. Best choice.
Corded rotary dialMaybeA bought adapter must support pulse dialing. Your own board can count pulses in firmware (section 6).
Phones with a real bell ringerYesLoud. Test the volume with each model; your own board rings at about 60 to 65 Vrms, quieter than a real phone line.
Cordless, office/PBX, digital or ISDN phonesNoThey need their own base or a proprietary line.

Checks before you buy

  • Is it a plain corded analog phone with a standard modular (RJ11) plug on the line cord? Four-prong plugs need an adapter.
  • Is it push-button? If it has a tone/pulse switch, set it to tone.
  • Does the seller say it was tested, and do they accept returns? Many vintage listings do not.
  • Use one phone per adapter, so the ring has enough power.

The two eBay phones you asked about

ListingWhat I sawAsk the seller
AT&T cream push-button, $35 + $7.50 shipping"Mechanical ringer" in the title, used, no returns, empty description, push-button keypad in the photo.Tone/pulse switch? Modular plug? Tested?
Western Electric Trimline, orange, $39.99 + $10.99 shippingPush-button, corded, desk or wall, listed "Untested", no returns, "movie prop" keywords.Photo of the bottom label (REN, plug)? Ever tested? Bell or electronic ringer?

Both should be electrically standard, but neither listing confirms it works. Test any phone on a bought adapter first.

4. The server

Which server to buy

Get a basic virtual server (VPS) with a fixed public IP address, running Debian 12. Four phones need very little, and your budget of under $100 a month leaves lots of room.

OptionEst. monthlyWhy or why not
DigitalOcean droplet (recommended)$12 to $24Simplest. Clear control panel and guides, free built-in firewall, fixed public IP, a New York region (low delay for NYC), several TB of transfer included.
Vultr or Linode$10 to $24Almost the same; also have US East regions.
AWS Lightsail$12 to $24Also simple, but ties you into AWS accounts and billing.
Hetzner Cloud$5 to $12Cheapest, US East location in Virginia, but stricter sign-up and a less beginner-friendly interface.
AWS EC2$15 to $30 plus data feesAvoid for now: more setup (security groups, elastic IP, NAT addresses) and outbound data is billed per GB.

Pick: DigitalOcean, New York region, Debian 12, the 2 GB plan (about $12 a month). Prices change; check the pricing page (I have not opened it).

Setup, step by step

For four phones, Asterisk is the quickest to configure and is in the Debian repositories. You can switch to Kamailio plus rtpengine later, when you want circle rules or many more phones.

1Create the server

Do
Create a Debian 12 droplet in the New York region. Add your SSH key and note its public IP.
Firewall
In the host's firewall settings allow only: TCP 22 (SSH), UDP 5060 (SIP) and UDP 10000 to 20000 (audio).

2Install the software

sudo apt update && sudo apt install -y asterisk fail2ban ufw
sudo ufw allow 22/tcp && sudo ufw allow 5060/udp && sudo ufw allow 10000:20000/udp
sudo ufw enable

3Define the four phones

Edit /etc/asterisk/pjsip.conf. Use a different long random password (20 or more characters) for each phone, and replace YOUR_SERVER_PUBLIC_IP.

Show pjsip.conf
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
external_media_address=YOUR_SERVER_PUBLIC_IP
external_signaling_address=YOUR_SERVER_PUBLIC_IP

[phone-endpoint](!)
type=endpoint
context=rotary
disallow=all
allow=ulaw
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes

[phone-auth](!)
type=auth
auth_type=userpass

[phone-aor](!)
type=aor
max_contacts=1
remove_existing=yes
qualify_frequency=30

[101](phone-endpoint)
auth=101
aors=101
[101](phone-auth)
username=101
password=CHANGE_ME_1
[101](phone-aor)

[102](phone-endpoint)
auth=102
aors=102
[102](phone-auth)
username=102
password=CHANGE_ME_2
[102](phone-aor)

[103](phone-endpoint)
auth=103
aors=103
[103](phone-auth)
username=103
password=CHANGE_ME_3
[103](phone-aor)

[104](phone-endpoint)
auth=104
aors=104
[104](phone-auth)
username=104
password=CHANGE_ME_4
[104](phone-aor)

4Set the dialing rules

Edit /etc/asterisk/extensions.conf. Calls go only between 101 and 104. Everything else, including 911, plays a message and hangs up.

[rotary]
; Calls between the four Rotary phones only
exten => _10[1-4],1,NoOp(Rotary call to ${EXTEN})
 same => n,Dial(PJSIP/${EXTEN},45)
 same => n,Hangup()

; Everything else, including 911, plays a message and hangs up
exten => _X.,1,NoOp(Blocked: ${EXTEN})
 same => n,Playback(ss-noservice)
 same => n,Hangup()

Later, record your own message ("This Rotary phone can only call other Rotary phones. It cannot call 911. Use your mobile phone for emergencies.") and play that instead of ss-noservice.

5Start and check

sudo systemctl restart asterisk
sudo asterisk -rx "pjsip show endpoints"

You should see 101 to 104 listed. They show as unavailable until the phones register.

How the server works

The phones sit behind home routers, so they cannot find each other directly. The server does four jobs: phone book (who is where), switchboard (connect the call), audio relay (pass the sound along) and rule keeper (only 101 to 104).

Phone 101 Server Phone 102 1. REGISTER 101 with password 200 OK (repeats about every 30 s) Lift handset: dial tone, then dial 102 2. INVITE 102 checks rule: 101 to 104 only finds where 102 is registered 3. INVITE 102 phone rings 180 Ringing 180 Ringing (ringback tone) 102 picks up 4. 200 OK 200 OK ACK ACK 5. Audio (RTP, about 87 kbps each way) flows both ways every packet is relayed by the server 6. BYE (someone hangs up) BYE
Figure 2. One call, start to finish. Solid arrows are requests, dashed arrows are replies.
  1. Register. When a phone powers up, its adapter sends the server its extension and password. The server records where it can be reached. The adapter repeats a small message about every 30 seconds so the router keeps the connection open.
  2. Dial. The adapter plays dial tone itself, reads the keypad tones, and asks the server for the extension.
  3. Route. The server checks the rule (101 to 104 only) and forwards the call to the registered address.
  4. Ring and answer. The other adapter rings its phone. You hear ringback. When it is answered, the call connects.
  5. Audio. Both phones send their audio to the server, which passes it to the other side. This is why calls work through any router.
  6. Anything else dialed, including 911, matches the catch-all rule and plays a message.

Security basics: long random passwords, only the three port ranges open, fail2ban running, no anonymous SIP. Later, add SIP over TLS and SRTP.

5. Get four phones working (bought adapters)

This is the fast path, and it is what your friends will use. You need four phones, four Grandstream HT801 adapters, four Ethernet cables and the server from section 4.

Old phone RJ11 line cord Adapter (HT801 style) PHONE ETHERNET POWER port names vary by model Home router free LAN port phone cord Ethernet cable 5 V power adapter (included)
Figure 3. Cabling for each home. The adapter connects to the router by cable only.

1Connect it

Do
Plug the phone into the adapter's phone port. Plug the adapter's Ethernet port into a free router port. Power it on.
Tip
If the router has no free port, add a cheap 5-port switch.

2Open its web page

Do
Find the adapter's IP address (lift the phone and use the keypad menu, or check the router's device list) and open it in a browser.

3Enter the SIP settings

SettingValue
Primary SIP serverYour server's IP or domain
SIP user ID and authenticate ID101 (then 102, 103, 104 for the others)
Authenticate passwordThe matching password from pjsip.conf
Preferred vocoderPCMU (G.711 u-law) only
NAT keep-aliveOn
Dial plan{ 10[1-4] } so it dials right after three digits

Menu names differ by model; these are for a Grandstream-style adapter.

4Save and check

Do
Save, reboot, and check that the status page shows "Registered". Then change the adapter's own admin password and, if you can, reserve a fixed IP for it in the router.
Works if
pjsip show endpoints on the server lists the phone as available.

6. Build your own adapter

The adapter does three jobs. A phone-line module powers the phone, rings it and senses when you lift the handset. An audio codec turns voice into digital samples and back. An ESP32-S3 runs the firmware: tones, keypad detection, and the phone protocol (SIP and RTP) over Ethernet.

Read firstI have not built or tested this. Part names are examples. Pin names and figures below come from the Silvertel Ag1171 datasheet V1.6, all pages you shared (through section 9, Package). Check the current datasheet and your own module before wiring.

Parts and the module

Old phone RJ11 jack Protection datasheet Figure 4 Ag1171 phone-line module power, ring, hook detect Audio codec ES8311 (recommended) ESP32-S3 tones, keypad detection, SIP and RTP, state machine W5500 Ethernet RJ45 jack Home router then the internet Power certified 5 V adapter, then 3.3 V rail feeds Ag1171, ESP32-S3, codec, W5500 tip and ring wires VOUT (mic) VIN (earpiece) I2S, I2C RM, F/R out; SHK in SPI cable
Figure 4. How the parts connect. The ESP32-S3 controls ringing and reads the hook switch directly, and it moves audio through the codec.

The phone-line module: Silvertel Ag1171

A single-supply (3.3 V to 5 V) phone-line interface in a 14-pin package, with a built-in DC-DC converter and ringing generator, 600 ohm impedance. It gives the phone a constant 26 mA at 3.3 V (30 mA at 5 V), rings it with up to about 65 Vrms (no load), and detects the hook with a logic output.

Phone line Control (ESP32-S3) Audio (codec) Power Do not connect Ag1171 pin 1 end 1234567 891011121314 RING (B) TIP (A) F/R (ring toggle) RM (ring mode) SHK (off-hook) NC NC NC VIN (audio in) VOUT (audio out) NC GNDPWR +VPWR (3.3 to 5 V) PD (leave open)
Figure 5. Ag1171 pins, redrawn from the datasheet's pin table and package figure (pin 1 at the right end). Check the pin 1 marking on your module before wiring.

Module facts from the datasheet

TopicFigure
Size and pins61 mm long, 12 mm high, 6.5 mm thick. Pins 0.6 mm thick, 2.54 mm pitch, two groups of 7 about 12.7 mm apart. Silvertel recommends 2.54 mm sockets for prototypes and a 1.1 mm PCB hole diameter.
Supply3.1 V to 5.5 V recommended; 7.0 V absolute maximum. Run at 3.3 V (see wiring).
Supply current at 3.3 VOn-hook 70 mA typical, 105 mA max. Ringing one phone 350 mA typical, 500 mA max. Off-hook 360 mA typical, 450 mA max. Power-down 5 mA.
Loop current26 mA at 3.3 V, 30 mA at 5 V (300 ohm load).
Control inputs RM, F/R at 3.3 VLow 0.5 V max, high 2.0 V min. At 5 V the high level must be 3.5 V or more, so a 3.3 V ESP32-S3 cannot drive them directly.
SHK outputAt 3.3 V: low 0.5 V max, high 2.8 V min. At 5 V: high 4.5 V min. Internal 3.3 kohm pull-up, 100 uA max output.
TimingWake-up 50 ms (outputs invalid). SHK detect about 5 ms. SHK debounce 10 ms. RM-high persistence 10 ms after ring trip. Tip-ring reversal settling 50 ms.
Ringing65 Vrms with no load at 20 Hz. Rings 3 phones with tone ringers or 2 phones with mechanical bells at 40 Vrms. Ring trip works up to 470 ohms including the phone.
Audio0 dB gain each way (plus or minus 0.75 dB). VIN input impedance 60 kohm. VOUT output impedance 10 ohm, designed for a 10 kohm load through 100 nF. Idle noise about 5 dBrnC.
Echo (transhybrid loss)Only 12 dB at 300 to 500 Hz, 21 dB at 500 to 2500 Hz, 16 dB at 2500 to 3400 Hz. Expect audible echo without echo control.

Parts for one bench prototype

PartExampleEst. costRole
Phone-line moduleSilvertel Ag1171, from DigiKey or Mouserabout $8 to $9Line power, ring, hook detect, audio
MicrocontrollerESP32-S3 module or small dev board (8 MB flash, PSRAM)$3 to $6Runs everything
EthernetW5500 module with RJ45$2 to $4Wired network
Audio codecES8311 board$2 to $4Analog audio to digital and back
Protection and filter partsPer datasheet Figure 4 (see below)about $3Protect the module and filter the supply
PowerCertified 5 V wall adapter$3 to $8Plus a 3.3 V regulator for the logic
Phone jackRJ11 jackabout $1Plug the phone cord in
Module socketsTwo 7-pin 2.54 mm female header stripsabout $1Spaced like the module's two pin groups, so you can swap modules
Board and enclosurePrototype board, small plastic box$7 to $15Mounting and safety
Totalabout $50 to $75

An AliExpress listing for the Ag1171 at $1 to $3 is far below DigiKey's price of about $8.50. It may be a different or fake part. This is the part that sends ring voltage to a phone, so buy genuine units for the first prototype (two, so you have a spare). You also need a multimeter.

The protection circuit (datasheet Figure 4)

Build the circuit from the datasheet's Figure 4 between the phone jack and pins 1 and 2. Do not improvise it. The parts it lists:

RefPartPurpose
D2 to D51N4004 diodes or an MB4S bridgePolarity and ESD protection
D182 V suppressor: BZT03C82 or P6KE82Overvoltage; one per line card
R120 kohm to 39 kohmOnly for caller ID on-hook transmission. Skip it.
C1, C2100 nF and 470 uF 16 V electrolyticDecoupling at the +VPWR pin
C3100 nFCoupling capacitor on VOUT
C410 nFCoupling capacitor on VIN
D61N4148 or BAS16Only if you use power-down; otherwise leave PD open
Optional2 x 1 nF, tip and ring to groundEMI suppression (Figure 5 of the datasheet)

For in-home use the datasheet says only ESD protection is needed (not lightning or power-cross protection), and it strongly discourages varistors and gas discharge tubes.

Wiring

SignalFromToNotes
Supply3.3 V railAg1171 +VPWR (13), GNDPWR (12)Datasheet range 3.1 V to 5.5 V; absolute maximum 7.0 V. Clean, regulated supply. 100 nF and 470 uF at the pin. Run it at 3.3 V so the ESP32-S3 can drive RM and F/R directly.
Ring modeESP32-S3 GPIO4Ag1171 RM (4)High only while ringing
Ring toggleESP32-S3 GPIO5Ag1171 F/R (3)High normally; toggled at 20 to 25 Hz to ring
Hook detectAg1171 SHK (5)ESP32-S3 GPIO6 (input)High when off-hook (at least 2.8 V on a 3.3 V supply). Debounce 10 ms. Goes straight into the ESP32-S3 at 3.3 V; at 5 V it outputs about 4.5 V, so level-shift down.
Phone lineAg1171 RING (1), TIP (2)RJ11 jack, through protectionOnly the two center wires of the jack
Audio to phoneCodec outputAg1171 VIN (9), through 10 nFCheck levels first
Audio from phoneAg1171 VOUT (10), through 100 nFCodec inputUse a resistor divider if it is too large for the codec
I2SESP32-S3 GPIO7 (MCLK), 15 (BCLK), 16 (WS), 17 (data out), 18 (data in)Codec8 kHz, 16-bit, mono
I2CESP32-S3 GPIO8 (SDA), 9 (SCL)CodecCodec setup
SPIESP32-S3 GPIO10 (CS), 11 (MOSI), 12 (SCLK), 13 (MISO), 14 (INT), 21 (RST)W5500Ethernet

The GPIO numbers are my suggestion; check them against the pin map of your ESP32-S3 board and avoid pins used for flash, PSRAM and boot straps.

Power budgetAt 3.3 V the module alone draws about 350 mA typical (500 mA max) while ringing and 360 to 450 mA off-hook. Add the ESP32-S3, the Ethernet module and the codec. Use a 3.3 V regulator rated for at least 1 A with headroom (for example a 2 A buck converter from the 5 V adapter), plenty of decoupling, and keep power tracks short and thick. A sagging supply will show up as resets or noisy audio, especially at ring time.
Audio levels and couplingThe module's gain is 0 dB in both directions, so you set levels in the codec. VOUT has a 10 ohm output impedance and is designed for a load of about 10 kohm through 100 nF, so pick a codec input of 10 kohm or more (with 10 kohm the 100 nF corner is about 160 Hz). VIN has a 60 kohm input impedance, so the datasheet's 10 nF coupling capacitor rolls off below about 265 Hz; if voices sound thin, try 22 nF to 47 nF. Measure VOUT with a scope or audio app before connecting it to the codec.
Plan for echoThe module's transhybrid loss is only 12 to 21 dB, which means part of the audio you send into the earpiece leaks back into the microphone path. Over a relayed internet call the far side will hear their own voice come back. Plan echo cancellation or at least echo suppression in firmware (see Firmware plan), and test on a real call early.
RM ring mode F/R polarity 0 s12345678 s RM high 1 s RM low 3 s (33% duty limit) F/R toggles 20 to 25 times a second (not to scale) F/R held high between bursts
Figure 6. Ring cadence: RM high for 1 second while F/R toggles at 20 to 25 Hz, then RM low for 3 seconds. The module limits RM-high to 33% of the time, so 1 s on and 3 s off follows the datasheet figure.

Ten build steps

Do these in order. Do not move on until each one works.

1Power the module, no phone

Wire
3.3 V to +VPWR, ground to GNDPWR, 100 nF and 470 uF at pin 13. Leave PD open. Tie RM low and F/R high. Leave tip and ring open.
Do
Power up from 3.3 V. Wait at least 50 ms (the module needs about 50 ms before its outputs are valid). Measure DC volts between the TIP and RING pins, and measure the supply current.
Works if
You read roughly 48 V DC (the datasheet's battery feed, adjusted to the line), and the supply current is about 70 mA at 3.3 V on-hook (datasheet maximum 105 mA). If either is wildly off, power down and check the wiring and supply.
Care
The module's supply must never exceed 7 V, even briefly.

2Hook detect

Wire
Add the protection circuit and the RJ11 jack. Connect SHK to ESP32-S3 GPIO6 (through a divider or level shifter if the module is on 5 V).
Do
Plug in a phone. Print the SHK level to the serial console. Lift and replace the handset a few times.
Works if
SHK reads high while the handset is up and low when it is down, with no flicker after a 10 ms debounce.

3Ring the phone

Do
Drive RM high for 1 s and toggle F/R at 20 Hz while RM is high, then RM low for 3 s. See the code under "Firmware plan".
Works if
The phone rings in a 1 s on, 3 s off pattern. Lift the handset during a ring and watch SHK pulse, then stay high.
Care
Hands off the phone-line terminals while ringing. Use one phone only.

4Answer during a ring (ring trip)

Do
When SHK goes high during ringing, the datasheet says to: debounce it for 10 ms; set F/R high; then set RM low more than 10 ms and less than 500 ms later. Do not drop RM sooner, so the ring voltage has time to decay. SHK detect takes about 5 ms and the datasheet lists a 10 ms RM-high persistence after ring trip.
Works if
Lifting the handset mid-ring stops the ringing cleanly and SHK stays high.

5Audio loopback

Wire
Codec to ESP32-S3 over I2S and I2C. Ag1171 VOUT through 100 nF to the codec input. Codec output through 10 nF to VIN.
Do
Start with low gain. Capture from the codec and play straight back. Speak into the handset.
Works if
You hear yourself clearly in the earpiece, without a squeal or loud hiss. Raise gain slowly; too much gain causes echo.
If thin
VIN's input impedance is about 60 kohm, so the 10 nF capacitor rolls off below about 265 Hz. Try 22 nF to 47 nF if voices sound thin.

6Play tones

Do
Generate dial tone (350 + 440 Hz, continuous) and play it when the handset is lifted. Add ringback (440 + 480 Hz, 2 s on, 4 s off), busy (480 + 620 Hz, 0.5 s on, 0.5 s off) and fast-busy (480 + 620 Hz, 0.25 s on, 0.25 s off).
Formula
sample = A * (sin(2*pi*f1*n/8000) + sin(2*pi*f2*n/8000)) / 2, with each tone at about -12 dBFS.
Works if
Each tone sounds like a normal phone tone.

7Read the keypad

Do
Run Goertzel detection on the audio from the handset (see the code below). Print each detected digit.
Works if
Pressing 1 to 4 gives clean digits, and talking does not produce stray digits.
Rotary
For pulse phones, count SHK pulses instead: one pulse for 1 up to ten for 0, with a pause between digits. Measure the timings on your own phones.

8Ethernet and SIP registration

Wire
W5500 to ESP32-S3 over SPI, RJ45 to the router.
Do
Get an IP address and ping the server. Then send a SIP REGISTER with digest authentication as extension 101, with an expiry of 60 to 120 s, re-registering at half that, plus a keep-alive every 20 to 30 s.
Works if
pjsip show endpoints on the server shows 101 as available.

9Make and receive calls

Do
Call a bought adapter (or a softphone app) at 102. Then call yours from 102. Use PCMU only, 160 samples (20 ms) per packet, send audio from the same port you listen on, and a jitter buffer of 40 to 60 ms.
Works if
Both directions have clear audio, hang-up from either side ends the call, dialing any other number gives the blocked message, and you do not hear your own voice echo back. The module's echo loss is only 12 to 21 dB, so expect to need echo control.

10Enclose it and soak test

Do
Put it all in a closed box, with strain relief on the cables and a certified power adapter. Enable a hardware watchdog. Leave it registered for a week and make a call every day.
Works if
It re-registers by itself after a power cut or a router reboot, and calls stay clear.

Firmware plan

Build on ESP-IDF with ESP-ADF audio helpers. Run these tasks: hook (reads SHK, debounces, sends events), ring (drives RM and F/R, handles ring trip), audio (20 ms frames to and from the codec, mixes in tones), DTMF (digit detection while no call is up), network (SIP and RTP) and a state machine tying them together.

For SIP and RTP, from most work to least: check whether ESP-ADF's SIP component covers REGISTER with digest auth, INVITE, CANCEL, BYE and G.711; write a minimal SIP client yourself (about eight message types); or first prove the whole design on a Linux board with a mature library such as baresip or PJSIP, then port it.

Echo control. Because the module leaks 12 to 21 dB of the earpiece audio back into the microphone path, plan an echo canceller that uses the audio you are playing as its reference. ESP-ADF and the Espressif speech libraries include an acoustic echo canceller; check whether it suits a short electrical echo like this one, or write a simple suppressor that lowers the transmit level while the far side is speaking.

Call states

StateEventAction, then new state
IDLEOff-hookPlay dial tone. DIAL_TONE
IDLEIncoming INVITEStart ringing. RINGING_IN
DIAL_TONEFirst digitStop the tone. COLLECTING
DIAL_TONE10 s with no digitPlay fast-busy. WAIT_ONHOOK
COLLECTINGNumber matches 10[1-4], or 4 s with no digitSend INVITE. CALLING (invalid number: fast-busy, WAIT_ONHOOK)
CALLING180 RingingPlay ringback
CALLING200 OKSend ACK, start audio. CONNECTED
CALLINGBusy or error responsePlay busy. WAIT_ONHOOK
CALLINGOn-hookSend CANCEL. IDLE
RINGING_INOff-hook (ring trip)Run the ring-trip steps, send 200 OK, start audio. CONNECTED
RINGING_INCaller sends CANCELStop ringing. IDLE
CONNECTEDOn-hookSend BYE, stop audio. IDLE
CONNECTEDBYE receivedPlay fast-busy. WAIT_ONHOOK
WAIT_ONHOOKOn-hookStop the tone. IDLE
Code: ring with ring trip (ESP-IDF, C)
#define PIN_RM  GPIO_NUM_4
#define PIN_FR  GPIO_NUM_5
#define PIN_SHK GPIO_NUM_6

// Returns true if the handset was lifted during the ring.
// Set CONFIG_FREERTOS_HZ=1000 so a 25 ms delay is accurate.
bool ring_once_with_trip(void) {
    gpio_set_level(PIN_RM, 1);                          // ringing mode on
    for (int i = 0; i < 20; i++) {                      // 20 cycles at 20 Hz = 1 s
        gpio_set_level(PIN_FR, 0); vTaskDelay(pdMS_TO_TICKS(25));
        gpio_set_level(PIN_FR, 1); vTaskDelay(pdMS_TO_TICKS(25));
        if (shk_high_for_ms(10)) {                      // debounced off-hook
            gpio_set_level(PIN_FR, 1);                  // forward polarity
            vTaskDelay(pdMS_TO_TICKS(20));              // more than 10 ms, less than 500 ms
            gpio_set_level(PIN_RM, 0);                  // end ringing
            return true;
        }
    }
    gpio_set_level(PIN_RM, 0);
    vTaskDelay(pdMS_TO_TICKS(3000));                    // 3 s silent (RM duty 25%)
    return false;
}

The SHK signal pulses during ring trip, per the datasheet figure. Measure its real shape on your module and adjust shk_high_for_ms to match.

Code: keypad detection with Goertzel (C)
#include <math.h>
#include <stdint.h>

// Power of one frequency f in a block of N samples at sample rate fs
float goertzel_power(const int16_t *x, int N, float f, float fs) {
    float c = 2.0f * cosf(2.0f * (float)M_PI * f / fs);
    float s0, s1 = 0.0f, s2 = 0.0f;
    for (int i = 0; i < N; i++) {
        s0 = (float)x[i] + c * s1 - s2;
        s2 = s1;
        s1 = s0;
    }
    return s1 * s1 + s2 * s2 - c * s1 * s2;
}

// Use N = 205 samples at 8000 Hz. Check these seven frequencies:
// low group:  697, 770, 852, 941      high group: 1209, 1336, 1477

Digit rules, so voice does not trigger false digits: the strongest low tone and strongest high tone must each stand well above the others in their group (for example 10 dB) and above a minimum level; the same digit must appear in at least two blocks in a row; and detection is off while a call is connected.

1209 Hz1336 Hz1477 Hz
697 Hz123
770 Hz456
852 Hz789
941 Hz*0#
Does it suit your phones?At 3.3 V the module gives a constant 26 mA of loop current (30 mA at 5 V), enough for old carbon-microphone phones, and about 65 Vrms of ring voltage with no load. At 40 Vrms it rings three tone-ringer phones or two mechanical-bell phones, so one phone per board is well within its limit. That should ring the two eBay phones, though more quietly than a real phone line. Test each phone on the bench.

7. Test plan

Do all of this with the four phones in two or three locations, before handing them out.

8. Trial with friends (2 weeks)

This is only for you and your friends: no investment, no customers, no pre-sale. Give a phone to each of three friends and keep one. Ask them to just use them.

Track in a simple table: date, who called whom, length, and planned or spontaneous. Check the server log with:

sudo asterisk -rx "cdr show status"

Ask each friend after two weeks

  1. How many times did you call, and who started most calls?
  2. What did you do differently with this phone than with your mobile?
  3. What annoyed you? (setup, ring volume, sound quality, cord, size)
  4. What would make you use it more?
Success looks likeEach phone averages 5 or more calls a week, and at least three of the four of you want to keep yours plugged in after the trial.

9. Purchase list

Prices come from listings and search results seen in November 2026 and will change. Check each page, stock and shipping before ordering.

For the 4-phone trial (bought adapters)

ItemQtyWhereEst. price
AT&T cream push-button phone1eBay 168672182892$35 + $7.50 shipping
Western Electric Trimline, orange (untested)1eBay 257837650036$39.99 + $10.99 shipping
Two more push-button corded phones2eBay or a thrift store$35 to $40 each + shipping
Grandstream HT801 adapter (check HT801 vs V2)4The Telecom Spot, eBay seller, CDW (V2)$34 to $50 each
Ethernet cable, 15 to 25 ft4Any retailer$8 each
RJ11 phone cord, power stripAny retailer$10
DigitalOcean droplet, New York, Debian 12, 2 GB1DigitalOcean pricing (not opened)about $12 a month
Estimated totalabout $395 plus $12 a month

For the DIY adapter (one bench prototype)

ItemQtyLinkEst. price
Line interface: Silvertel Ag11712DigiKey AG1171about $8.50 each
ESP32-S3 module1ESP32-S3-WROOM-1-N8R2$5.88 (0 in stock when I looked; restock estimate 25 Nov 2026)
Ethernet module1WIZ850io or an AliExpress W5500 module$20 to $25 on DigiKey; $2 to $4 on AliExpress
Audio codec (recommended)1ES8311 board from AliExpressabout $2 to $4
Alternative codec1SGTL5000 chipabout $1.58 on a reel; tiny package
Alternative: DAC and ADC pair1Adafruit PCM5102 (6250) plus a PCM1808 board; DigiKey sells only the bare PCM1808PW chip$7 to $9; fixed levels need dividers
Protection and filter parts (Figure 4)1 setAny distributorabout $3
5 V power supply1Adafruit 5V 2A (276)about $8; add a matching barrel-jack socket
RJ11 jack1Adam Tech MTJ-649X1 or Molex 0424106314about $1
Two 7-pin 2.54 mm female header strips (module sockets)1 setAny retailerabout $1
Prototype board, jumper wires, enclosure1Any retailer$10 to $15
Multimeter (if you do not have one)1Any retailerabout $20
Estimated totalabout $50 (cheap modules) to $75 (mostly DigiKey), excluding the multimeter

Suggested order

  1. Message the two eBay sellers with the questions in section 3, and buy the phones that pass.
  2. Buy the four HT801 adapters, cables and cords, and create the server.
  3. Order two Ag1171 modules and the ESP32-S3 module while the trial runs.
  4. Order the codec, protection parts and enclosure. Check the datasheet's later electrical characteristics before choosing level-matching resistors.

10. Common problems

SymptomTry this
Registers, but no sound or one-way audioCheck UDP 10000 to 20000 is open in the server's firewall and that external_media_address is set.
Phone will not registerCheck user ID, password and server address; confirm UDP 5060 is open; check the Ethernet cable and link light.
Adapter gets no IP addressTry a different router port, or reboot the router.
Phone does not ringTry another phone, and give each adapter one phone only. On your own board, check RM and F/R and the supply.
Rotary phone does not dialUse a push-button phone, or check pulse support (bought adapter) or SHK pulse counting (your own board).
Calls drop after minutesTurn on NAT keep-alive in the adapter.
Strange calls or failed logins in the logYou are being scanned. Use long passwords, keep fail2ban running, and open only the listed ports.
Own board: sounds thinTry a larger capacitor on VIN (22 nF to 47 nF); the 10 nF value rolls off below about 265 Hz.
Own board: far side hears an echoLower the gain and add echo cancellation or suppression; the module only gives 12 to 21 dB of echo loss.
Own board: resets or noise when ringingThe supply is sagging. Ringing draws about 350 mA typical (500 mA max) at 3.3 V; use a regulator rated for 1 A or more and add decoupling.

11. What comes next (optional)

Nothing here needs money or customers. It is only for you and your friends. If you love it:

  • Your own adapter: finish section 6 and swap it in for one friend's phone.
  • Server v2: Kamailio as the registrar and proxy and rtpengine for audio relay, with rules for who may ring whom instead of fixed extensions.
  • Share it: publish the server configs, firmware and board files so others can copy your setup.
  • Later, only if you want to: decide together whether to build more phones for other people.