Firmware for the
ESP32-DIV v1
handheld.
Forked from cifertech ESP32-DIV v1.1.0 and extended with additional features.
- Target: ESP32-WROOM-32 (plain ESP32, NOT S3)
- Board: ESP32-DIV v1 (main board + shield)
- Display: ILI9341 240×320 SPI TFT
- Touch: XPT2046 resistive
- Buttons: 5 × tactile via PCF8574 I²C expander (0x20)
- Radios on board: 3 × NRF24L01+, 1 × CC1101 (sub-GHz), ESP32's own WiFi/BT
Requires arduino-cli and ESP32 Arduino core 2.0.17 (later cores have not been
tested; the project uses Bodmer's TFT_eSPI via a bundled User_Setup.h).
arduino-cli compile \
--fqbn "esp32:esp32:esp32:PartitionScheme=huge_app,FlashSize=4M,CPUFreq=240,FlashFreq=80,FlashMode=qio" \
--build-property "compiler.c.elf.extra_flags=-Wl,-zmuldefs" \
.Flash:
arduino-cli upload \
--fqbn esp32:esp32:esp32:PartitionScheme=huge_app \
--port /dev/cu.usbserial-0001 \
.The -Wl,-zmuldefs is needed because TFT_eSPI ships some symbols that the
core's stock Bluetooth stack also defines; without it the link fails on
multiple-definition errors.
| Subsystem | Bus / signal | GPIO |
|---|---|---|
| TFT (ILI9341) | HSPI native — MISO/MOSI/SCLK/CS | 12 / 13 / 14 / 15 |
| TFT | DC, RST, backlight | 2, 0, 4 |
| Touch (XPT2046) | HSPI via matrix — CLK/MISO/MOSI/CS | 25 / 35 / 32 / 33 |
| Touch | IRQ (PENIRQ) | 34 |
| SD card | VSPI native — SCK/MISO/MOSI/CS | 18 / 19 / 23 / 5 |
| NRF24 #1 (U2) | CE / CSN | 4 / 5 |
| NRF24 #2 (U3) | CE / CSN | 26 / 27 |
| NRF24 #3 (U4) | CE / CSN | 16 / 17 |
| CC1101 (U1) | SCK/MISO/MOSI/CSN/GDO0/GDO2 | 18 / 19 / 23 / 27 / 26 / 16 |
| PCF8574 (buttons) | I²C SDA / SCL | 21 / 22 |
| Battery monitor | ADC | 36 |
| GPS UART (optional, header) | RX / TX | 17 / 4 |
| NeoPixels (WS2812) | DIN | 1 |
- GPIO 4: TFT backlight AND NRF24 #1 CE.
- GPIO 5: SD CS AND NRF24 #1 CSN. SD and NRF24 #1 are mutually exclusive — the SD driver and the RF24 driver both want this pin.
- GPIO 16: NRF24 #3 CE AND CC1101 GDO2. Sub-GHz "RX data" and the
third NRF24 share this line; the firmware enforces one-at-a-time use
via
subghzReleasePinsFromNrf()on every SubGHz feature entry. - GPIO 26: NRF24 #2 CE AND CC1101 GDO0. Same one-at-a-time deal.
- GPIO 27: NRF24 #2 CSN AND CC1101 CSN. 2.4 GHz and sub-GHz radios
are mutually exclusive — they both want this pin as chip-select. The
CC1101 driver claims it via
cc1101InitForDivV1()(which callsELECHOUSE_cc1101.setSpiPin(18,19,23,27)— the library default of SS=5 is wrong for DIV v1 and was a latent bug fixed in v0.0.3). - GPIO 25 / 32: XPT2046 touchscreen CLK/MOSI. Do not wire GPS or any UART here — earlier versions of this firmware did and it killed touch for the rest of the session. As of v0.0.3 the GPS pins are 17/4, both reachable from the exposed shield header.
The PCB has no GPS receiver on board, but the shield's expansion header
(J3, TSM-110-04-S-DV) breaks out enough free pins to bolt one on. The
ATGM336H is cheap, ubiquitous, runs from 3.3 V, and speaks NMEA over UART
at 9600 8N1 by default — which is what Hydra's gps.cpp expects.
⚠ Status: Work In Progress. The firmware-side support is in (
gps.cpp,gps_status.cpp, GPS-tagged wardrive features), but the author has not yet physically soldered an ATGM336H module to their board. Wiring below is based on the schematic and the firmware's pin map; please verify with a meter on first power-up and open an issue with corrections if anything is off.
- 1 × ATGM336H GPS module (typically sold on a breakout PCB with an SMA or IPEX antenna pad — both work). The version with the active patch antenna on the board itself is the easiest.
- A few cm of wire, or four 2.54 mm female jumpers if you want it removable.
The shield's 10×2 expansion header (silkscreen labels IO16/IO17/etc.)
exposes both GPIOs Hydra wants for GPS. Solder to those pins; no
soldering to the ESP32 module itself is needed.
| ATGM336H pin | Header silkscreen | ESP32 GPIO |
|---|---|---|
| VCC | 3v3 |
— |
| GND | GND (either one) |
— |
| TX (module → ESP32) | IO17 |
GPIO 17 |
| RX (ESP32 → module) | IO4 |
GPIO 4 |
Power the module from 3V3, NOT 5V — the ATGM336H IC is a 3V3 part, and the ESP32 GPIOs are also 3V3. Wiring it to the shield's 5V rail will work the GPS chip's regulator hard and may level-shift TX above the ESP32's input tolerance.
The chosen pins are the least-conflicted GPIOs on the shield header, but neither is truly exclusive — every header pin has a primary peripheral function on this board.
- GPIO 17 is also NRF24 #3 CSN. Hydra's NRF24 #3 is rarely active (most NRF features use NRF #1 or #2), but if you run a feature that drives NRF3 — currently none of the shipped features do — GPS data on this pin will be corrupted while NRF3 is selecting.
- GPIO 4 is the TFT backlight AND NRF24 #1 CE. The firmware drives the backlight HIGH at boot and never toggles it, so steady-state GPS TX coexists. The brief CE pulses NRF24 #1 issues during 2.4 GHz features won't reach the GPS as anything meaningful (GPS treats it as line noise). GPS RX (the line FROM ESP32 TO module) is normally idle HIGH anyway since we don't send config commands.
- Earlier docs pointed at GPIO 32 / 25 — those are the XPT2046 touchscreen CLK/MOSI lines and are NOT on the exposed header. Wiring GPS there killed touch for the rest of the session.
After soldering and flashing, open Tools → GPS Status. With a clear sky view (or antenna at a window) you should see:
- "Sats: N" climb to a non-zero number within ~30 s of cold-start
- Time/date update once N ≥ 4 satellites
- Lat/Lon populate once you have a fix
If "Sats" stays at 0 forever:
- Confirm TX/RX aren't swapped (this is by far the most common mistake; the labels on cheap modules vary)
- Check VCC at the module pin with a meter (should be 3.30–3.33 V)
- Some ATGM336H clones boot at 38400 baud; if so, edit
HYDRA_GPS_BAUDingps.hto 38400 and reflash
-
PCF8574 init order. Call
pcf.pinMode()for every button pin BEFOREpcf.begin(). The library'sbyteBufferedcache is initialised inside anif (writeMode>0 || readMode>0)block; with begin-first, it stays at 0, making every pull-up pin read LOW on its firstdigitalRead. Symptom: serial log at boot shows all 5 buttons "Pressed" and the menu auto-selects itself. SeeHydra.inosetup() comment. -
Touch on HSPI, not VSPI.
Touchscreen.cppcreatesSPIClass(HSPI)and routes pins 25/35/32/33 via the GPIO matrix. TFT_eSPI uses HSPI's native pins via IO_MUX direct routing, so the two coexist on the same peripheral. If you ever move touch back to VSPI, everySD.begin(5)call will steal VSPI's MISO away from the touchscreen for the rest of the session. -
CC1101 SPI pins must be explicitly set.
ELECHOUSE_cc1101.Init()on its own uses the library's ESP32 default (SS=5), but DIV v1 wires CC1101 CSN to GPIO 27. BareInit()leaves the chip's CSN floating and every SPI command (setMHZ, setRx, etc.) silently fails. Every SubGHz feature must callcc1101InitForDivV1()(insub_shared.h) instead. Was a latent bug in cifertech v1.1.0 / Hydra v0.0.1–v0.0.2, fixed in v0.0.3. -
No SD probe in the status bar.
utils.cpp::drawStatusBar()does NOT callisSDCardAvailable(); the status bar SD indicator is hardcoded to "absent". The cifertech upstream did probe SD on every status update, which works on v1 but causes intermittent CC1101 corruption on cards with slower CMD response. Individual SD features mount the card themselves on entry — that's the only place SD.begin() should appear at runtime. -
SD.begin(5)after a feature exit doesn't always re-mount cleanly. The Arduino ESP32 SD library caches_pdrvand returns true on subsequentbegin()calls without re-running pin setup. If you exit an SD feature and then enter another, the second feature usually inherits a working mount. If you exit an NRF24 #1 feature that drove GPIO 5 (NRF24 #1 CSN) and then enter an SD feature, forcepinMode(5, OUTPUT); digitalWrite(5, HIGH);beforeSD.begin(5)to give the card a clean CS edge (seeesppwnagotchi.cpp).
The submenu structure roughly follows cifertech upstream. Highlights of what Hydra added over v1.1.0:
- WiFi: AP scan, deauth (single/multi/evil), CSA attack, SAE attack, probe flood, beacon spoof, hidden-SSID reveal, ESPPwnagotchi (handshake pcap to SD), evil-portal detect, Pineapple detect, Flipper detect, Rayban-Stories detect, Flock detect, AirTag detect, ESP-detect, multi-SSID detect, probe detect, pwn detect.
- Bluetooth: sniffer, jammer/spam, gotchi variants, freq detector.
- 2.4 GHz: scanner, replay, sniffer (NRF24), mode-jammer, mousejack, carrier, intermittent, triwatch, heatmap, BLE-adv generator, wardrive (NRF24 channel logging to CSV).
- Sub-GHz: spectrum analyzer, replay, sweep jammer, wardrive (CC1101 + GPS NMEA → CSV).
- Tools: GPS status, SD browser, SD format, target list, freq detector, skimmer detect.
- Frequency: wardrive channel viewer.
Hydra exists because of a long list of open-source hardware and firmware projects. Listed roughly in order of how much of their work is in here:
- cifertech — the ESP32-DIV v1 board hardware (schematic, PCB, BOM) and the v1.1.0 firmware Hydra was forked from. Pretty much everything that draws a menu, the touch UI, the WiFi/BLE attack scaffolding, and the sub-GHz code lineage starts here.
- justcallmekoko / ESP32Marauder — reference for WiFi scanning patterns, deauth, evil portal, beacon spoof, PMKID, EAPOL handshake capture, and a great deal more. Sets the bar for this class of firmware.
- Bruce — multi-tool firmware whose feature breadth and UX inspired several Hydra additions.
- RF-Clown / NRF Clown — NRF24 jamming, BLE-adv, intermittent / sweep patterns.
- AppleJuice, ESP32-Sour-Apple — Apple BLE spoofing / continuity packet techniques.
- ESP32-AirTag-Scanner — AirTag / FindMy detection.
- Momentum-Apps
ble_spam— BLE spam pattern catalogue (Flipper Zero port that we cross-referenced). - PwnGridSpam — fake Pwnagotchi adverts and the basis for our pwn-detect.
- flock-you — Flock ALPR-camera surveillance detection.
- opendroneid-core-c — drone Remote ID broadcast decoding.
- BlueJammer, SubMarine, Universal-RC-system — additional jamming / RC / sub-GHz reference work.
Libraries that do the heavy lifting:
- Bodmer/TFT_eSPI (bundled User_Setup for DIV v1)
- xreef/PCF8574 (with init-order caveat, see Gotchas above)
- PaulStoffregen/XPT2046_Touchscreen
- LSatan/SmartRC-CC1101-Driver-Lib
- nRF24/RF24
- stevemarple/MicroNMEA
If your project is on this device and not on this list, it's an oversight, not a slight — please open an issue / PR and we'll add you.
Hydra is free for personal, non-commercial use only. See
LICENSE for the full terms.
Files retained from the upstream cifertech ESP32-DIV v1.1.0 firmware remain
under the upstream MIT license (Copyright (c) 2023 CiferTech). Modifications
and new code added by the Hydra project are licensed under the personal-use
terms in LICENSE. Commercial use of the firmware as a whole requires
written permission — open a GitHub issue with the commercial license
label to start that conversation.
