All-band AM / FM / SW receive-only radio. ESP32-S3, SI4732-A10, 2.8" ILI9341. CiferTech, MIT, firmware v1.0.0.
Fennec is a handheld shortwave-listener radio. Receive only. No transmitter, no CAT control of another rig, and no station-memory scan list.
The SI4732-A10 does the RF. The ESP32-S3 runs the UI, the Wi-Fi face, the SSTV picture decoder, Morse copy, the RSSI homing plot, and an event logger. The LCD is the main face. The browser at http://192.168.4.1/ is a second face that follows the hardware, and the hardware follows the browser. It is not a button remote.
Boot lands on a muted menu. Audio stays off until you open RADIO or a tool that needs the speaker. That avoids the PAM8403 boot pop.
Coverage. FM 64-108 MHz and AM/SW 153 kHz-27.90 MHz. Airband, NOAA weather, VHF/UHF, and 10 m ham (28 MHz+) are out of range. That's the chip, not a firmware bug.
Five doors on the menu. About and Settings live in the corners. Only one decoder or logger runs at a time.
RADIO
FM, AM, shortwave. Seek, RDS, volume. Last place remembered in flash.
SSTV
Martin, Scottie, Robot 36. VIS auto or lock. Radio tap or mic.
MORSE
Goertzel copy from the tuner or the capsule. Pitch, USB/LSB, BFO.
HOMING
RSSI sparkline, about 8 seconds. You walk the antenna. Fennec is the meter.
WATCH
Park on a channel, ARM it, log when the carrier holds. 32 events in flash.
WEB
SSID Fennec. Phone and LCD stay in sync. Optional home Wi-Fi for NTP.
The RADIO face is AM/FM listening. USB/LSB is loaded when SSTV, Morse, or Watch need it. It is not a general SSB mode on RADIO.
There is hardware seek. There is no band-scan face and no station memory list. Those were removed on purpose.
WIKI / HARDWARE
Hardware
ESP32-S3 in the same touch-bus style as ESP32-DIV. Developed against Arduino-ESP32 core 2.0.10. Do not treat this as a 3.x project.
Core
ESP32-S3 - UI, Wi-Fi AP, decoders, I2S mic
SI4732-A10 - AM / FM / SW tuner (I2C). Probes 0x11 and 0x63 (SEN to GND or 3.3 V)
ILI9341 2.8" - 240x320 portrait, rotation 2
XPT2046 - touch on its own SPI bus, not shared with the TFT
PAM8403 - class-D amp. Mute GPIO 7 before analog outs power up
I2S MEMS mic - INMP441 / SPH0645 class, 16 kHz averaged down to 8 kHz
3x WS2812 on GPIO 38. Hue is locked to orange
3x tactile buttons - UP / OK / DOWN, active-LOW with internal pull-ups
GPIO map
Edit Pins.h if your PCB is different. TFT SPI pins must also match TFT_eSPI_User_Setup.h.
Function
GPIO
Notes
I2C SDA / SCL
8 / 9
4.7k pull-ups to 3.3 V
SI4732 reset
10
TFT MOSI / SCLK / MISO
11 / 12 / 13
FSPI
TFT CS / DC / RST / BL
14 / 21 / 47 / 48
Backlight PWM, never 0%
Touch MOSI / MISO / CLK / CS
35 / 37 / 36 / 18
Own SPI
Buttons UP / OK / DOWN
6 / 5 / 4
Tune / band / vol
Amp shutdown
7
LOW at boot = muted
Mic BCLK / WS / DATA
40 / 41 / 42
I2S
NeoPixel
38
3 LEDs
SSTV / CW ADC
1
LOUT via cap + mid-bias
Audio tap (required for SSTV and Morse from the radio)
SI4732 LOUT -> 1 uF capacitor -> GPIO 1 (ADC). Two 100 kOhm resistors as a mid-rail bias, one to 3.3 V, one to GND.
Without this wire, RADIO still plays through the PAM8403, Homing still works from RSSI, and Watch can still log RSSI. SSTV and Morse from the radio will have nothing to decode. You can still feed those tools from the MEMS mic.
Speaker path: SI4732 LOUT/ROUT through DC-blocking caps into the PAM8403. Keep the amp shutdown pin under firmware control.
Buttons
Touch is primary. Three buttons are the fallback.
Short
Hold (~0.7 s)
UP (GPIO 6)
Tune up
Volume up
OK (GPIO 5)
Next band
Seek
DOWN (GPIO 4)
Tune down
Volume down
In a tool: tune is 1 kHz steps, OK flips USB/LSB (or PEAK on Homing), long OK goes back. Hold UP+DOWN from any face to return to the menu. There is no rotary encoder.
WIKI / FLASH
Flash with Arduino IDE
The sketch folder must be named Fennec. Stay on Arduino-ESP32 2.0.10. Core 3.x breaks the NeoPixel RMT code.
Boards Manager: add https://espressif.github.io/arduino-esp32/package_esp32_index.json if needed, then install esp32 by Espressif. Use 2.0.10 if you can.
Tools -> Board -> ESP32S3 Dev Module.
Sketch -> Include Library -> Manage Libraries, install:
Copy TFT_eSPI_User_Setup.h over Documents/Arduino/libraries/TFT_eSPI/User_Setup.h. The sketch does not include that file. TFT_eSPI reads it from its own library folder. Paste it by hand once.
Open Fennec.ino and click Upload.
Suggested Tools menu
Setting
Value
USB CDC On Boot
Disabled for CP2102/CH340. Enabled for native USB-C
Flash Size
Match your module (8MB is common)
PSRAM
QSPI (N8R2) or OPI (N8R8). SSTV likes PSRAM for the web BMP
Upload Speed
921600
No tuner yet? Set FENNEC_SIMULATE_RADIO to 1 in Config.h to exercise the UI and web page with no SI4732 attached.
First boot
Hold OK while resetting, or send c on serial, to calibrate touch.
Join Wi-Fi SSID Fennec and open http://192.168.4.1/.
Serial at 115200. Send ? for commands.
WIKI / FACES / RADIO
Radio
FM, AM, shortwave. The chip's whole analog world, from long wave up through the broadcast bands, amateur stretches, and CB. Not airband. Not weather radio. Not VHF.
Tap FM, AM, or SW. The chips under the tabs are shortcuts: a full span, or Japan FM, or forty-nine meters. The big number is where you are. SEEK hunts a station. MUTE is a finger on the speaker. Volume lives on the bottom row.
Last place you were is remembered. Open RADIO tomorrow and you are still there.
Kind
Chips
FM
FULL, OIRT, Japan, ITU. Units are 10 kHz (6400-10800)
AM
FULL, LW, MW. MW step 9 kHz default, set 10 for the Americas
SW
FULL 1.71-27.9 MHz, meter bands, CB
RADIO is AM/FM listening, not general SSB. The SSB patch loads when SSTV, Morse, or Watch need USB/LSB.
WIKI / FACES / SSTV
SSTV
Shortwave still sends pictures. Slow-scan. A tone that paints a line, then another, until a face or a schematic is sitting on the glass.
Open SSTV. Fennec goes USB or LSB, listens for the VIS, and draws as the lines arrive. Martin M1/M2, Scottie S1/S2, Robot 36. Leave it on AUTO, or lock a mode if you already know the handshake.
Calling frequencies are on the keys:
Band
kHz
Sideband
80 m
3733
LSB
40 m
7171
LSB
20 m
14230
USB
15 m
21340
USB
RADIO listens through the tuner. MIC listens through the capsule. Hold a speaker to the mic if you must, and the amplifier goes quiet so Fennec does not copy itself. Nudge BFO until the picture locks. RESET if the image goes wrong. Walk away and come back: the picture is still there.
Needs the GPIO 1 audio tap, or MIC. Web BMP is at /api/sstv.bmp. Picture size is load-bearing. Don't casually change kSstvPic.
WIKI / FACES / MORSE
Morse
Dits and dahs on the air, and Fennec writes them down. A listener's copy, not a contest machine.
Open MORSE. Set the pitch to the tone you hear. That is PIT. Sideband with USB and LSB. BFO if the note sits off-center.
RADIO copies from the tuner. MIC copies from the capsule. The speaker mutes so the box does not hear itself. Hold the phone close. Echo is the enemy. Gaps fill, letters glue.
The first word waits a breath. Fennec is learning how fast they are sending. Then the text starts to run. Fifteen to thirty words a minute is the neighborhood.
Goertzel, 400-1200 Hz, 4 ms blocks. Pitch has to match the tone. Not reliable at QRQ or with a noisy speaker across the room.
WIKI / FACES / HOMING
Homing
You are not getting a compass bearing. You are getting a peak.
Open HOMING. A line crawls across the screen, about eight seconds of signal strength. The orange LEDs breathe with it. Walk. Turn the beam. When the trace climbs and the lights quicken, you are looking at the transmitter.
Tap PEAK to mark the high water and hunt again. A whip standing straight up will not point. You need a direction. You are the motor. Fennec is the meter.
RSSI sparkline only. Not Adcock, Doppler, or compass. No sidetone. ESP32-S3 has no DAC. You hear the radio, or nothing on MIC.
WIKI / FACES / WATCH
Watch
Some signals do not talk. They just appear.
Open WATCH. Park on a frequency: UVB-76, a known USB marker, or HERE, wherever you already sit. ARM it. When the carrier holds above the threshold, Fennec writes an event: time, frequency, how strong it got. Up to thirty-two of them, kept in flash.
Raise or lower the threshold. Clear the list when the night is done. This is a log for a shortwave listener, not a decoder of voices, and not a tool for anything that is not yours to hear.
Preset
kHz
Mode
4625
4625
AM
5448
5448
USB
6925
6925
USB
9074
9074
USB
HERE
current
stay put
Serial d dumps JSON. Events live in the same NVS namespace as band and volume.
WIKI / FACES / SETTINGS
Menu, About, Settings
Power on, and Fennec does not shout. One orange blink. The CiferTech mark on black sand. Then a quiet menu. Five tiles: RADIO, SSTV, MORSE, HOMING, WATCH. About and Settings live in the corners. Tap a tile when you are ready.
About
Who built it. What board. What chip. A mail, a GitHub, a site. Tap anywhere to go back.
Settings
Four taps. Wi-Fi access point on or off. When it is on, the address sits under the list. PIXEL, the three orange LEDs. BRIGHT, twenty percent at a time, never dark enough to lose the menu. TOUCH, if the glass and the finger disagree, or hold OK while it boots and walk the crosses.
Brightness 20-100, step 20. Hold OK at boot to calibrate. A short lock after Settings taps eats bounce so the page does not flicker.
WIKI / WEB REMOTE
Web remote
Same radio. Second glass.
Join the network named Fennec. Open a browser to http://192.168.4.1/. What you see is what the box is doing. Change a tab on the phone, and the LCD follows. Change the LCD, and the page follows.
RADIO on the web is the live tuner, speaker up, not the silent boot menu. SSTV shows the picture as it paints. Morse, homing, watch: the same tools, in your hand, across the room.
If you have a home network in the firmware, Fennec can join it too, take time from the internet, and put a clock in the header.
Set FENNEC_WIFI_AP_PASS (8+ characters) to encrypt the AP. Only one exclusive tool at a time, shared with the LCD.
HTTP
Path
GET /
tuner page
/api/status
JSON snapshot of the live face
/api/tune
?dir=1 or ?f=103.5 or ?f=6075
/api/band
?dir=1 or ?id= or ?kind= (0=FM 1=AM 2=SW)
/api/seek
?dir=1
/api/volume
?dir=1 or ?v=40 (0-63)
/api/mute
mute
/api/sstv
reset, mic=0/1, lock
GET /api/sstv.bmp
live picture
/api/mode
?m=tuner|sstv|cw|hunt|log
/api/usb/api/bfo
sideband and BFO
/api/cw
pitch or mic
/api/hunt
peak or JSON history
/api/log
arm, clr, thr, preset, or events JSON
WIKI / SERIAL
Serial
115200 baud. Send ? for help.
Key
n / p
next / previous band
[ / ]
tune down / up
s
seek up
+ / -
volume
m
mute
t
SSTV toggle
v
RADIO / MIC on SSTV or Morse
w
Morse toggle
h
Homing toggle
l
Watch toggle
d
dump Watch log
c
touch calibration
i
band / freq / vol / rssi / ip
WIKI / CONFIG
Config.h
Tunables. Pins stay in Pins.h.
Define
What it does
FENNEC_SIMULATE_RADIO
1 = UI / web without SI4732
FENNEC_MW_STEP_KHZ
9 or 10
FENNEC_DEFAULT_VOLUME
0-63
FENNEC_WIFI_AP_SSID / PASS
soft-AP. Empty pass = open
FENNEC_WIFI_STA_SSID / PASS
home network. Empty = skip
FENNEC_TZ
POSIX TZ. Default UTC0. Iran: IRST-3:30
FENNEC_NEOPIXEL_BRIGHT
0-255, currently 48
FENNEC_NEOPIXEL_ORDER_GRB
1. If green/red look swapped, try 0
FENNEC_MIC_SHIFT
I2S 32-bit to int16, default 14
FENNEC_TOUCH_DEBUG
1 = print raw X/Y/Z
FENNEC_DEFAULT_BRIGHTNESS
LCD percent
WIKI / FAQ
It doesn't work
Symptom
Check
White LCD
TFT_eSPI User_Setup.h not copied, or pins don't match Pins.h
No touch
Hold OK at boot to calibrate. Check the touch SPI pins
Boot thump
Amp SD pin polarity (PIN_AMP_SD_ACTIVE_HIGH)
One NeoPixel / stuck green
Need RMT_MEM_128 on core 2.0.10. RMT_MEM_64 is too small for 3 LEDs
Compile error on RMT
You are on Arduino-ESP32 3.x. Stay on 2.0.10
SSTV "no audio"
Missing GPIO 1 tap, or switch to MIC
Morse garbage
PIT vs the tone, too much echo on MIC, first-word wait
No AP
Wi-Fi off in Settings, or FENNEC_WIFI_ENABLE_AP is 0
No clock
STA SSID empty. NTP only after home Wi-Fi joins
Sketch not found
Folder not named Fennec
The long form of this list, plus what was intentionally removed, is in FENNEC.txt.
SI4732 programming follows Silicon Labs AN332 via PU2CLR SI4735. The SI4732-A10 SSB patch comes from that library. Don't redistribute Silicon Labs chip firmware as a commercial product.