Skip to content

Repository files navigation

Fusion_EDGE

FusionEdge

FusionEdge is an ESP32-S3 internet radio firmware built on the yoRadio codebase. It uses LovyanGFX and LittleFS and adds a 480x320 touch-oriented interface, spectrum and waveform visualizations, optional Bluetooth audio input, SD and DLNA playback, WebUI control, encoders, weather information and theme support.

The project grew from the LovyanGFX/LittleFS-based VTomRadio variant. FusionEdge keeps the original yoRadio playback architecture while substantially extending the display, controls, audio visualization and source handling.

Project status

FusionEdge is now feature-complete. Development focuses on confirmed bug fixes, hardware compatibility and selected community contributions.

Version 1.1.1

  • Prevents playlist touch scrolling from changing the volume when the gesture begins on the player screen
  • Refines the full-screen cover layout, including centered clock/weather content, safe nameday wrapping and artifact-free transparent text rendering
  • Uses attributed and HTTP-cached Last.fm metadata while retrieving artwork exclusively from Cover Art Archive via MusicBrainz release identifiers
  • Corrects IR previous/next and volume-button navigation direction in the channel list, including held-button repeats
  • Clears the RGB LED strip before every deep-sleep path so the final animation frame cannot remain illuminated

The artifact-free cover-screensaver text rendering in this release was contributed by Volodimyr Zagranichniy. Thank you for the continued testing and careful improvements.

Version 1.0.10

  • Adds an optional full-screen album-cover screensaver with current track, time, date, nameday and weather information
  • Improves multilingual Last.fm matching by normalizing punctuation, Unicode dashes and quotes, Cyrillic case and trailing technical IDs, and by matching any semicolon-separated artist together with the track title
  • Raises the accepted cover-image size to 512 KB while retaining PSRAM-backed storage and cooperative network handling
  • Adds configurable backlight PWM frequency and Wi-Fi TX power defaults to reduce audio interference and supply-current peaks on sensitive hardware
  • Adds optional BTN_MODE and BTN_RGB controls for source switching, LED strip enable/disable and effect selection
  • Keeps RGB VU animation active during playback screensavers, including a dedicated Bluetooth VU source, and reserves the idle animation for silence
  • Makes WEB/SD/DLNA and Bluetooth transitions safer by coordinating decoder, I2S bridge and remote-source pause state
  • Corrects FLAC sample-buffer reuse, restores the gen4-ESP32-35CT landscape orientation and synchronizes the supported hardware configuration examples

The full-screen cover screensaver and most non-Bluetooth improvements in this release were contributed or proposed by Volodimyr Zagranichniy. Thank you for the careful development, testing and continued refinement.

Version 1.0.9

  • Applies the configurable clock-screensaver brightness to both idle playback states and the While playing clock when the cassette screensaver is not compiled in
  • Coordinates clock brightness, ambient-light control and automatic fading; with LIGHT_SENSOR enabled, the clock setting scales the sensor-controlled brightness instead of replacing it
  • Refreshes the current station or album-cover image immediately after leaving the clock screensaver
  • Improves Last.fm fallback matching by checking more search results while retaining strict artist priority and guarded title-only matching
  • Scott Barber's independent community MOD has moved to its own repository, where it can be maintained separately from the main firmware

Version 1.0.8

  • Added a configurable 0-100% brightness level for the While not playing clock screensaver
  • Restores the normal display brightness on wake and keeps the setting compatible with the automatic backlight fade feature
  • Migrates existing configurations automatically with a 100% default, so a full flash erase is not required

Version 1.0.7

  • Fixed SD playback metadata propagation so embedded artist/title tags can trigger album-cover lookup, with the filename retained as a fallback
  • Preserves the last valid SD track across restarts and safely resets the stored index when the card contents no longer contain that track
  • Added an experimental classic ESP32-WROVER-E N16R8 compatibility package with target-specific PSRAM allocation, wake-mode and GPIO safeguards
  • Kept all WROVER memory changes isolated from the primary ESP32-S3 build

Version 1.0.6

  • Stabilized DLNA browser initialization, category loading, playlist import and switching between DLNA and WEB playlists
  • Improved HTTPS stream reliability by coordinating CoverArt, DLNA and audio network operations and reducing internal-memory pressure
  • Fetches the largest available Last.fm album image directly, with MusicBrainz and Cover Art Archive retained as fallbacks
  • Gives stream changes priority over background cover downloads, preventing a new station name from appearing while the previous station keeps playing
  • Improved stream-stall and Wi-Fi reconnection recovery while preserving the user's playback intent
  • Fixed WebUI file-serving races that could crash player.html or leave the display locked after an interrupted request
  • Fixed automatic backlight fading, including invalid legacy settings and a zero fade-step value
  • Prevented the built-in LED and NeoPixel strip from competing for GPIO48
  • Added an optional ESP32-WROVER-E N16R8 PlatformIO configuration template

Version 1.0.5

  • Optional current-track album art from Last.fm, MusicBrainz and Cover Art Archive for WEB, SD, DLNA and Bluetooth playback
  • A more reliable asynchronous DLNA WebUI browser with configured root-folder support and paged directory listings
  • Correct source icons and mode handling when switching between DLNA, WEB and Bluetooth playback
  • Serialized, low-priority cover and DLNA network work to preserve audio playback memory and watchdog responsiveness

Main target

  • ESP32-S3 with PSRAM
  • 480x320 ILI9486, ILI9488, ST7796 or AXS15231B display
  • LovyanGFX display driver
  • XPT2046 resistive or supported I2C capacitive touch controller
  • External I2S DAC or amplifier
  • Optional QCC5124EL Bluetooth module using UART AT commands and an I2S audio bridge
  • Optional SD card, DLNA, MQTT, IR receiver, LED strip and RTC

Hardware pins and optional features are selected in myoptions.h. Bluetooth support is compiled only when USE_BLUETOOTH is defined.

Build

The supplied platformio.ini targets an ESP32-S3 DevKitC-1 N16R8 board using the pioarduino Arduino core.

  1. Install Visual Studio Code, PlatformIO, or PlatformIO Core.
  2. Review myoptions.h and mytheme.h for your hardware.
  3. Copy data/data/wifi.example.csv to data/data/wifi.csv and enter your Wi-Fi credentials, or configure Wi-Fi through the radio's access point.
  4. Build and upload the firmware.
  5. Upload the data directory as a LittleFS filesystem image.

An experimental classic ESP32-WROVER-E N16R8 package is available in esp32-wrover-n16r8. It contains a matching platformio.ini, example myoptions.h, installation steps and the known hardware limitations. The ESP32-S3 remains the recommended target: the WROVER WebUI can be slow during playback, and HTTPS streams may fail when sufficient contiguous internal RAM is unavailable for the TLS handshake.

data/data/wifi.csv is intentionally ignored by Git because it contains local network credentials.

Typical PlatformIO commands:

pio run
pio run --target upload
pio run --target uploadfs
pio device monitor

The serial monitor speed is 460800 baud.

Scott Barber community MOD

Scott Barber's independent community build is maintained separately in the FusionEdgePlus2 repository. It adds layouts for smaller displays, including ILI9341 support, automatic tape color changes, and selectable screensaver styles including album-cover art. The MOD has its own source tree, configuration and documentation and does not automatically receive changes from the main FusionEdge firmware.

Bluetooth

The tested Bluetooth path uses a QCC5124EL module:

  • QCC5124EL module purchase link

  • Select Bundle: HFP and Color: 5124 I2S when ordering; other variants are not the tested FusionEdge configuration

  • UART AT control on the pins configured by BT_UART_TX and BT_UART_RX

  • I2S input on BT_I2S_BCK, BT_I2S_LRCK and BT_I2S_DATA

  • No MCLK connection is required by the tested module configuration

  • Metadata, touch/encoder/WebUI mode switching and spectrum visualization are supported

The working bridge parameters are kept in src/core/bluetooth_config.h.

DLNA browser

When USE_DLNA is enabled, set dlnaHost to the media server address and dlnaIDX to the preferred root object ID in myoptions.h. The DLNA page in the WebUI opens at that configured root, lists folders and tracks, and can build or append entries to the playback list.

Directory browsing runs through a background worker instead of the web-server callback. This keeps SOAP requests away from the AsyncTCP task and makes larger or slower media-server libraries considerably more reliable. The WebUI and firmware endpoints are version-dependent, so upload the matching v1.1.1 LittleFS data along with the firmware when upgrading from an earlier release.

Last.fm album art

Current-track album art can optionally replace the station/source icon in WEB, SD, DLNA and Bluetooth modes. Create a Last.fm API account, then add the following to myoptions.h:

#define USE_LASTFM_COVER
#define LASTFM_API_KEY "your_lastfm_api_key"

The lookup runs in a low-priority background task and only starts when metadata contains both an artist and a title in Artist - Title form. FusionEdge uses Last.fm for metadata matching and an album MusicBrainz ID when available. It otherwise searches MusicBrainz for a matching release group, then retrieves the image from Cover Art Archive. Images are kept in PSRAM and are not written to LittleFS. While a cover is unavailable, downloading or invalid, the normal station or source icon remains visible.

Last.fm metadata responses use a small PSRAM cache which follows the server's Cache-Control and Expires instructions. Responses marked no-store or no-cache are not reused.

Bluetooth metadata receives an additional fallback for video services. If the QCC artist field contains a channel name and the exact lookup fails, FusionEdge cleans the video title and resolves it with Last.fm track.search. Local files still use their exact embedded artist and title metadata first.

Search-result comparison ignores common ASCII and Unicode punctuation and normalizes Cyrillic case. A trailing numeric technical ID after a semicolon is removed before searching, and metadata containing multiple semicolon-separated artists can match when the title and at least one artist agree.

Cover lookup uses plain HTTP and keeps its task stack and JSON allocations in PSRAM. This is intentional: opening another TLS session can consume the contiguous internal RAM required by HTTPS audio streams on the ESP32-S3. Only the Last.fm API key is sent; do not add a Last.fm shared secret to the firmware.

This integration uses metadata from Last.fm and MusicBrainz, and cover art from the Cover Art Archive. The WebUI includes a visible link crediting Last.fm. Review the Last.fm API terms, retain that credit in redistributed builds, and respect the rights of artists and labels when using Cover Art Archive images.

Weather units

Weather values use metric units by default: Celsius, hPa and km/h. To display Fahrenheit, inHg and mph, select LANGUAGE EN and define IMPERIALUNIT in myoptions.h. A build-time check prevents this option from being combined with locale files that currently contain metric-only weather format strings.

The IMPERIALUNIT weather-unit option was reintroduced by Adam Navrowski.

Album-cover screensaver

Define USE_COVER_SCREENSAVER in myoptions.h to use the current album cover as the non-blank While playing screensaver. It displays the current artist and track alongside the time, date, nameday and weather. When no downloaded cover is available, the normal station or source image is used instead.

This option currently requires a 480 x 320 display and PSRAM. It cannot be enabled together with USE_CASSETTE_SCREENSAVER; select one of the two styles at build time. The album-cover screensaver was created and contributed by Volodimyr Zagranichniy.

Cassette screensaver

Define USE_CASSETTE_SCREENSAVER in myoptions.h to enable the animated vintage cassette. In the WebUI, enable the While playing screensaver, set its timeout in seconds, and leave its Blank screen option disabled. During playback the cassette shows the current artist and track title; without stream metadata it falls back to the station name and a PLAYING label. The lower label displays the available codec, bitrate, sample-rate and bit-depth information. The normal idle screensaver remains the large clock, while Blank screen continues to switch the display off.

The WebUI Clock brightness (%) setting controls the large-clock screensaver brightness. It always applies to While not playing, and also to While playing when USE_CASSETTE_SCREENSAVER is not defined. The cassette screensaver continues to use the normal display brightness. When LIGHT_SENSOR is configured, this value scales the current automatic brightness instead: for example, 50% displays the clock at half of the ambient-light-controlled brightness.

The cassette idea and original animation prototype were contributed by Adam Navrowski. The FusionEdge implementation redraws only the two reel areas during animation to keep display traffic low. The supplied background is stored at /images/screensaver/retro_audio_cassette.png; CASSETTE_PNG_PATH can point to a replacement image with the same 456 x 291 pixel layout. Blue/pink and red/cream alternatives are supplied as retro_audio_cassette_blue.png and retro_audio_cassette_red.png in the same directory. CASSETTE_FRAME_MS can optionally set the reel refresh interval; the default is 100 ms. If the PNG or its PSRAM-backed sprite cannot be loaded, FusionEdge falls back to the code-drawn cassette.

Display note

Some ST7796 panels require the Invert display WebUI option for correct colors. This is a panel/controller variation and is currently a known hardware-specific setting.

When an ST7796, XPT2046 and SD card share the same SPI bus, some modules may show display artifacts during SD playback. Other tested display/touch combinations do not exhibit this behavior.

For the Guition JC3248W535 with its integrated AXS15231B QSPI display and touch controller, use the tested configuration in AXS15231B_options. The final AXS15231B driver stabilization and hardware testing were completed by Tibor Botfai.

For the 4D Systems gen4-ESP32-35CT with its integrated ILI9488 display, FocalTech capacitive touch controller and microSD slot, use the configuration in gen4-ESP32-35CT_options. It uses the same ILI9488 driver as regular SPI modules, with board-specific pins and bus settings supplied through myoptions.h.

To add logos for your own stations, see the custom station icon guide.

Project history and credits

  • yoRadio by e2002 and contributors
  • VTomRadio LovyanGFX/LittleFS yoRadio variant by VTom
  • ESP32-audioI2S by schreibfaul1
  • Final AXS15231B driver stabilization and hardware testing by Tibor Botfai
  • 4D Systems gen4-ESP32-35CT board support by Révész Tamás
  • Reintroduction of IMPERIALUNIT weather-unit support by Adam Navrowski
  • Cassette screensaver concept and original prototype by Adam Navrowski
  • Full-screen album-cover screensaver, multilingual cover matching and backlight/Wi-Fi hardware tuning by Volodimyr Zagranichniy
  • Smaller-display and selectable-screensaver community MOD by Scott Barber
  • FusionEdge development by SimZs and contributors

Bundled and external components retain their own copyrights and licenses. See THIRD_PARTY_NOTICES.md.

License

FusionEdge is distributed under the GNU General Public License v3.0. See LICENSE.

About

ESP32 based internet radio with DLNA & Bluetooth source support

Resources

Stars

26 stars

Watchers

6 watching

Forks

Releases

Packages

Contributors

Languages