Bring-up
What the simulator could not check, in the order to check it on a newly assembled minimal board
(DESIGN.md). Every step uses the firmware’s serial console (olp> on the USB-C port, see
firmware/README.md). Write the results into firmware/TESTLOG.md (step, PASS/FAIL, numbers).
Tools: a USB-C cable and a computer with ESP-IDF v5.5, a wired handset with a 3.5 mm TRRS (CTIA) plug, a multimeter; nice to have: a phone with a sound-level-meter app, a second handset or headset.
0. Power and flashing
Section titled “0. Power and flashing”- Before the module is powered: no short between 3V3 and GND (> 1 kΩ).
- Plug USB-C: 3V3 = 3.25-3.35 V at the LDO output. Current with the firmware idle: < 150 mA.
idf.py -p <port> flash monitor. If the port doesn’t appear: hold BOOT, press RESET, release (hw v0.2: hold BOOT while plugging USB in instead, §8.2).- The boot log shows
Open Lounge Phone firmware,fingerprint: …, the display draws.
1. Keys, hook, jack, ringer, LED
Section titled “1. Keys, hook, jack, ringer, LED”- Press each key: the log prints
KEY 1…KEY 0,KEY MENU,KEY BACKonce per press. - Lift/replace the handset:
HOOK up/HOOK down. Plug/unplug the handset:JACK in/JACK out. statusshows the state; call the phone from the app to hear the piezo and see the LED ring.- Walk through
docs/phone-ux.md: each screen, the menu (MENU, a digit, BACK, MENU), the LED patterns (dim ready, pulse connecting, blink offline, fast flash ringing, on in a call) and the beeps. Anything that differs from the page is a bug: note it infirmware/TESTLOG.md.
2. Codec on I2C
Section titled “2. Codec on I2C”- The boot log must show
ES8311 (id 8311) ready: 16 kHz, mic PGA 30 dB, scale-up 6 dBandaudio device: es8311. If it saysES8311 not foundoraudio device: test: check SDA IO18 / SCL IO17, the 4.7 kΩ pull-ups, CE to GND (address 0x18) and the codec’s 3V3. audioprintsAUDIO device=es8311 ….
3. Earpiece: tones and the volume cap
Section titled “3. Earpiece: tones and the volume cap”The earpiece plays only with the handset lifted; audio tone overrides that for bring-up.
audio tone test(1 kHz): a clean tone in the earpiece.audio tone nonestops it.audio tone dialtone,ringback,busy,hold: compare with a landline (350+440 Hz steady; 440+480 Hz 2 s on / 4 s off; 480+620 Hz 0.5 s / 0.5 s; a short 440 Hz beep every 4 s).- Level check (the cap):
volume 10(the maximum),audio tone test, the earpiece held to a sound-level meter (a phone app is fine, 1-2 cm from the earpiece): write down the dB SPL. The firmware cap isCONFIG_OLP_EARPIECE_MAX_DB= -6 dBFS by default (hardware owner question 8: full scale was estimated at ≈ 98 dB SPL with the assumed receiver). If volume 10 is uncomfortably loud, lower the cap inidf.py menuconfig→ Open Lounge Phone → Call audio and note the value; each volume step is 3 dB (volume 0…volume 10, also MENU → 1). - Unplug the handset while a tone plays: no crackle or pop worse than a click.
- Hang up (
HOOK down) withaudio toneoff: the earpiece is silent (DAC muted).
4. Microphone: levels
Section titled “4. Microphone: levels”audio loop 300: the mic plays back in the earpiece 300 ms later (an echo test; the delay keeps it from howling). The mic is on only while the loopback runs.- Speak normally into the handset:
audioshowsmiclevel=(at the ADC, before the AGC) about -30 to -20 dBFS andspeech=(after the AGC) near -24; silence below -55 dBFS. The phone check shows it without a console: MENU 7 with the handset up switches the mic on and itsMICrow readsSPEAK NOW: -24 DB OKevery second. This sets the analog gain default (PGA 30 dB + 6 dB scale-up, a first board read speech peaks around -38 dBFS at PGA 18 dB): with each handset, a normal voice must readOK(notWEAK) and shouting must not readTOO LOUD(micpeak=inaudiostays below -1 dBFS). If not, try other gains live withaudio gain <pga 0-30 dB> [scale-up 0-42 dB](for exampleaudio gain 30 0,audio gain 30 12) and put the one that works for all handsets inCONFIG_OLP_MIC_PGA_DB/CONFIG_OLP_MIC_SCALE_DB(audio gainisn’t saved).audio agc offcompares without the AGC. - You hear yourself 0.3 s later, clearly, with no hum or buzz. A 50/60 Hz hum points at the mic bias filter (1 kΩ / 10 µF) or a ground loop through the USB supply.
- Tap the handset’s button (if it has one): note whether the log shows a level spike (the board
doesn’t wire the button;
DESIGN.md§7). audio loop off.audiomust now show the mic off (call=0, nomiclevelupdates): the mic is captured only in a call or in this test.
5. A real call
Section titled “5. A real call”- Pair the phone (README “Pairing a phone”), put the companion on the allow-list.
- Lift, press the key for the companion: ringback in the earpiece; the companion rings.
- Answer in the companion: the log shows
RTC CONNECTED: ICE + DTLS-SRTP up in … msand every 5 sAUDIO tx=… rx=… under=….txandrxgrow by ~250 per 5 s;under(underruns) stays small (a few per minute at most). - Talk both ways. The companion hears the handset clearly; the handset hears the companion at a comfortable level at the default volume (6/10).
- Codec and timing: the
AUDIOline sayscodec=opus/opuswith the companion,dry=0(the earpiece never ran dry with the 1 ms DMA blocks),conceal=small, and the CPU per 20 ms frame:enc=(Opus encode),dec=andaec=(average/worst µs; together well under 20000). Note them. A listening test against firmware 0.9.5 (PCMU): s, f and th should be clearer. - Sidetone: in a call you hear yourself faintly, right away (no echo-like delay); MENU 1 6 cycles off / low / normal. Note which sounds right. Mute (MENU 3): the sidetone stops.
- Echo with the handset: with the handset held normally, MENU 7 then 2 (the echo test):
note the
ECHOrow (38 DB OK, 4 MS) for each reference handset, and at volumes 6 and 10. TheMSis the sidetone’s delay too: it must be under 5. Then talk from the companion with the handset on a table and held normally: the companion should not hear itself back; noteerl=/erlbest=in theAUDIOline. Repeat with MENU 1 7ECHO CANCEL ON(next call):erle=shows what it removed; the companion’s echo should be gone and the phone user’s voice unchanged when both talk at once. These numbers decide whether the canceller is on by default (CONFIG_OLP_ECHO_CANCEL). rtcshows the selected ICE servers;ice tcpthen a new call forces TURN over TCP/TLS (for networks that block UDP): the call must still connect.- Hang up with the hook:
call media off (mic off)in the log; the companion shows the call ended.
6. Wi-Fi setup network
Section titled “6. Wi-Fi setup network”wifi forget,reboot: the display showsWI-FI SETUP: JOIN,OPENLOUNGEPHONE-XXXX,PASSWORD dddddddd,OPEN 192.168.4.1; the log showsPROV AP UP.- From an iPhone and an Android phone: join the network with the displayed password. The OS should open the setup page by itself (captive portal); if not, open http://192.168.4.1/. Note which OS did what.
- The page lists nearby networks. Try a wrong-length password (refused on the page), then the right one: “Saved”, the phone restarts, joins, and pairs as usual.
- Hold MENU+BACK while plugging in USB:
KEEP HOLDING→ after 3 sRELEASE: WI-FI(release: setup opens) → after 10 sFACTORY RESET(release: Wi-Fi, owner and keys erased; it asks for Wi-Fi setup again). - Turn the home router off for 3+ minutes: the setup network opens; turn it back on: it closes and the phone reconnects.
7. Release firmware on a board (encrypted storage, signed updates)
Section titled “7. Release firmware on a board (encrypted storage, signed updates)”Only on a board meant to stay a phone: a release build burns an eFuse key on its first boot, one-time and irreversible (firmware/README.md “Encrypted storage”).
idf.py -B build-release … flashof a release build (tools/release.sh build), or an update to one.- First boot:
FIRST ENCRYPTED BOOT: burning a new NVS HMAC key into eFuse KEY5, thenSTORAGE encrypted (… new).espefuse.py summaryshows KEY5 with purposeHMAC_UPand read-protected. - Set up Wi-Fi and pair; restart:
STORAGE encrypted (… existing), same four words, signs in. esptool.py read_flash 0x9000 0x6000 nvs.bin: the Wi-Fi name and password don’t appear in it.- Remove the phone in the app:
WIPE: NVS partition erased, a new pairing code, Wi-Fi kept.
8. hw v0.2 only: wired network and PoE
Section titled “8. hw v0.2 only: wired network and PoE”The v0.2 board adds an RJ45 (J4) with PoE magnetics, a W5500 (U4) on the display’s SPI bus and
an isolated 802.3af PoE module (PS1), diode-OR’d with USB into the 5 V rail V5 (DESIGN.md §12a).
Flash the v0.2 build (firmware/README.md “Building for each board”: sdkconfig.v02,
board id minimal-v02); the rev A build never touches the W5500. How the firmware drives it
and chooses between the cable and Wi-Fi: firmware/README.md “Wired network”. Until the
firmware runs, the PHY idles at ~65 mA in auto-negotiation (USB peak 526 mA vs 500 in the
budget: fine on any real charger, but note it); the firmware powers it down while on Wi-Fi.
Power for these tests (hardware/README.md “Power”): a v0.2 phone runs from PoE or a real USB-C charger. The debug setup is PoE plus a computer’s USB for the console: the PoE cable carries the load, the computer port only flashes and reads the console. Don’t run the network tests from a computer port alone: with the PHY and Wi-Fi on together the board draws more than its 500 mA. Steps 1-2 (straps, download mode) are fine on a computer port alone (no network yet).
- Straps, before anything else. USB only, no Ethernet cable. Measure GPIO45 (U4 pin 34, ETH_MISO) and GPIO0 (U4 pin 32, ETH_CS) at power-up and while RESET is held: GPIO45 < 0.4 V, GPIO0 > 3.0 V. The boot log must show the flash and PSRAM as before (a 1.8 V VDD_SPI shows up as a flash ID failure).
- Download mode with BOOT. Hold BOOT and plug USB in (a power-up, so the W5500 is still in
reset when the straps latch): the port appears in download mode,
esptool.py flash_idreads the 3.3 V flash. Holding BOOT and pressing only RESET is the one case where the W5500 is not reset; prefer a power cycle (or the USB-JTAG auto-download, which never uses GPIO0). A BOOT press while the phone runs can’t select the W5500: the GPIO drives CS high against the 1 kΩ (3.3 mA). - 5 V OR. USB only: V5 ≈ VBUS − 0.4 V. PoE only (a PoE switch or injector, USB unplugged): POE_5V ≈ 5.27 V at PS1, V5 ≈ 4.9 V, VBUS at an open receptacle may float a little through D3’s leakage (harmless, no current). Both: V5 follows the higher source, nothing gets warm, the USB console still works.
- PoE classification. On the switch: class 0, ~3 W drawn in a call. The module must not whine at idle (< 100 mA load): if it does, fit R28 (51 Ω 2512, not fitted by default).
- Isolation. Unpowered, PS1 and J4 in place: > 10 MΩ from J4’s PoE pins (7-10) and BR1/BR2 to GND at 500 V DC if a megger is at hand; never connect the PoE side to the USB ground.
- The W5500 answers. USB only, no cable, Wi-Fi saved. The boot log shows
ETH W5500 ready, mac xx:xx:…(the chip’s Ethernet MAC, the eFuse base + 3) andETH PHY on (looking for a link);ETH: no W5500 answeringmeans SPI: check U4’s supply (U5, 3.3 V), its 25 MHz crystal, the CS (IO0) and MISO (IO45) lines with a scope during the first second. After ~5 s:NET settled: Wi-Fi (no usable cable),NET Wi-Fi radio on,ETH PHY off (power-down). Measure the 5 V current with the PHY off and during a look (every 30 s,ETH PHY onfor ~6 s): the difference is the PHY’s (~65 mA expected). - Link and DHCP. Plug a cable from a switch with a DHCP server. Within 30 s (the next look):
the RJ45’s green LED (link) lights, yellow (activity) flickers, the log shows
ETH link up 100 Mbit/s full duplex,ETH got ip=…,NET uplink wired ip=…,NET Wi-Fi off …,NET Wi-Fi radio off.ethprintsETH controller=W5500 phy=on link=up 100M full ip=… mac=… uplink=wired cable="WIRED NETWORK"; MENU 3 showsWIRED NETWORK/ the address. Try a 10 Mbit/s port or a forced half-duplex port if there is one (ethshows what was negotiated). Pair or sign in and make a call over the cable both ways (the audio counters inaudiogrow, no underruns beyond the usual). - Unplug and replug. Pull the cable:
ETH link down,NET uplink none: CABLE UNPLUGGED, the screenOFFLINE/CABLE UNPLUGGED, Wi-Fi joins within seconds (NET uplink wifi,NET switched to Wi-Fi: reconnecting to the server), backREADY; the PHY powers down 6 s after the pull. Plug it back within those 6 s: straight back on the cable. Later: back on the cable at the next look (≤ 30 s), Wi-Fi off. A call on Wi-Fi while the cable comes back stays on Wi-Fi (MENU 3:CABLE AFTER CALL) and moves when it ends; pulling the cable during a call ends the call (expected) and the phone comes back on Wi-Fi. - Cable only.
wifi forget,rebootwith the cable in: no setup network opens (PROV opennever appears), the phone comes online on the cable. Pull it:CABLE UNPLUGGED, the PHY stays on (noETH PHY off), replug: online again within a few seconds. MENU 3 → 1: the setup page says the cable is connected and Wi-Fi is optional, and saves a server alone. A switch port with no DHCP server:NO DHCP ON CABLEafter 15 s. - PoE only. Unplug USB: the phone keeps running from the cable alone (no reset, no reconnect: the diode-OR hands over). Power it up from PoE alone too (a PoE switch or an 802.3af/at injector; a passive 24 V injector must not power it): it boots, gets its address on the cable and makes a call. The console is gone (no USB), so watch the screen and the switch’s per-port power reading. Power-cycle it a few times from the switch. Minimum load: the PoE module needs at least 100 mA at 5 V or it whines and the switch may drop it (DESIGN.md §12a); measure the 5 V current at the module’s output (a USB power meter can’t see it: use a series shunt on POE_5V, or the switch’s reading ÷ ~48 V × efficiency) idle and in a call in every network mode: on the cable; on Wi-Fi with the PHY powered down (unplug the data side, e.g. a PoE injector whose LAN port is disconnected, so the phone falls back to Wi-Fi while still powered: the lowest draw, the one to watch); and during a cable check. Every mode must stay above 100 mA with margin; if Wi-Fi with the PHY down comes close, fit R28 (51 Ω 2512, ~100 mA) and record it.
- Display + Ethernet. A full e-paper refresh while a call streams over Ethernet (MENU 0
About, MENU 7 Phone check): no audio underruns beyond the usual (
audio), the picture is clean (the two share SCLK/MOSI), noPHYCFGR write … failedor SPI errors in the log. - BOOT while running. Press BOOT with the phone on the cable: nothing happens to the network (CS stays high through the 1 kΩ).
9. What to record
Section titled “9. What to record”Board serial / date, 3V3, idle current, the ES8311 id, the SPL at volume 10, the chosen cap,
miclevel for speech and for silence, the PGA gain and scale-up used, the phone check’s MIC
word per handset, call setup time (RTC CONNECTED … ms), underruns per minute, dry=, the
enc= / dec= / aec= times, the echo test per handset (loss and delay), erl= in calls,
whether echo was heard with the canceller off and on, the sidetone level chosen, and how each phone OS handled the setup page. On
hw v0.2: the eth line, the 5 V current with the PHY off and on, how long a plugged cable took
to be used, the switch’s PoE class and power, and any audio underruns during an e-paper refresh.