User Tools

Site Tools


pinebuds_anc

PineBuds Pro — ANC Analysis & Open Firmware

Factory firmware ANC coefficients extracted and integrated into OpenPineBuds (2026-04-08).

Hardware

  • SoC: BES2300YP (dual Cortex-M4F @ 300MHz)
  • ANC: Hardware-accelerated in codec silicon (not software DSP)
  • Paths: Feedforward (FF), Feedback (FB), Talk-Through (TT), Music Cancel (MC)
  • Flashing: USB-UART via charging case (WCH CH342, vendor 1a86)
  • Tool: bestool (Ralim, Rust) — cargo install –git https://github.com/Ralim/bestool

Flash Layout (4 MB)

Region Address Size Content
Bootloader 0x000000-0x014000 80 KB BES boot ROM, identical L/R
Gap 0x014000-0x018000 16 KB Erased
Firmware 0x018000-0x140000 1184 KB Main firmware, identical L/R, matches factory AC08
Unused 0x140000-0x3EC000 2736 KB Fully erased
NV Records 0x3EC000-0x3FE000 72 KB BT pairing, config, 116 bytes differ L/R
Erased 0x3FE000-0x3FF000 4 KB
Factory Cal 0x3FF000-0x400000 4 KB “PineBuds Pro” string, BT MAC, 17 bytes differ L/R

ANC Audio Section (0x3EE000)

Stored in flash at 0x3EE000. Header: magic=0xDAD1, version=1.

Extracted ANC Coefficients (factory firmware):

Path Gain (48k) Gain (44.1k) Biquads Status
Feedforward L 512 660 8 Active — full IIR chain
Feedforward R 0 0 1 (unity) Passthrough
Feedback L 512 512 6 Active — full IIR chain
Feedback R 0 0 1 (unity) Passthrough
Talk-Through 0 0 1 (bypass=1) Passthrough
Music Cancel 0 0 0 Not used

Key findings:

  • L = R identical — zero per-unit calibration from factory
  • Mono ANC — only left channel has real filters, right is passthrough
  • ADC gain offset: -6 dB on all active paths (prevents mic clipping)
  • 44.1 kHz FF gain is 660 vs 512 at 48 kHz — compensates for different spectral resolution
  • IIR coefficients are Q27 format (unity = 134217728 = 0x8000000)

Community ANC Status (as of 2026-04)

  • OpenPineBuds main branch: ANC listed as “non-functional, WIP”
  • anc-testing branch (2023): one tester got “pretty good” results with tuned gains
  • Merge blocked by CMake migration that never happened
  • anc-tuning branch: last commit Jan 2026, no merge
  • Root cause of bad ANC: empty coefficient arrays in open firmware
  • Our fix: extracted factory coefficients, integrated into config/open_source/tgt_hardware.c

Tools

anc_extract.py

Extracts ANC IIR coefficients from a bestool flash dump:

# Human-readable summary
python3 anc_extract.py backup_left.bin

# C header for OpenPineBuds integration
python3 anc_extract.py backup_left.bin --c-header > anc_coefs.h

Located in dev_tools/anc_extract.py in our OpenPineBuds fork.

bestool

# Backup firmware (CRITICAL — do this first!)
bestool read-image --port /dev/ttyACM0 backup_right.bin
bestool read-image --port /dev/ttyACM1 backup_left.bin

# Flash new firmware
bestool write-image out/open_source/open_source.bin --port /dev/ttyACM0

# Serial monitor (2 Mbaud)
bestool serial-monitor /dev/ttyACM0 --baud-rate 2000000

Repos

Build Environment

VM 120 pinebuds on data (192.168.88.44):

  • Debian 11, 4 cores, 4 GB RAM, 64 GB ZFS
  • ARM GCC 9-2019-q4-major at ~/gcc-arm-none-eabi-9-2019-q4-major/
  • bestool (Ralim) via cargo
  • Docker available but native build preferred (12 sec)
  • SPICE USB passthrough for CH342 charging case (vendor 1a86)
  • lmcp on port 8080
export PATH="$HOME/gcc-arm-none-eabi-9-2019-q4-major/bin:$PATH"
cd ~/OpenPineBuds
make -j4 T=open_source DEBUG=1
# Output: out/open_source/open_source.bin (883 KB)

Backups

Factory flash dumps stored on: hertz, data, boltzmann, pinebuds VM.

  • backup_left.bin — md5: 05c0200d73e99633d41d8e757dfc4d6c
  • backup_right.bin — md5: 0cf360d3a92fcddb39c3f9bf53f3b9fc
  • factory_AC08.bin — md5: 4d2810bdb6fc32ccea3a034538b3fbf7 (Pine64 download, code only)

Status

Phase: Firmware built with factory ANC coefficients. Awaiting flash test on actual hardware.

pinebuds_anc.txt · Last modified: by 127.0.0.1