Zero Axis Technologies
The BLE remote's populated radio board, showing its wireless SoC, PCB antenna, and flex connector to the button assembly

Building a five-button BLE remote that controls media and phone calls on iOS and Android

Challenge

A hardware team needed a small BLE remote - five buttons and a round color display - that could control media playback and phone calls on both iOS and Android, packing a wide command set onto just five buttons by distinguishing taps, multi-taps, and holds, showing live status on its own screen, and behaving sensibly through phone call interruptions. It also needed to be honest with testers about which commands actually work on which platform, since BLE HID delivery succeeding and the phone's OS actually acting on it are two different things testers could easily conflate.

Solution

We built the firmware on an nRF52840 running Zephyr (nRF Connect SDK), exposing a BLE HID-over-GATT service with a hand-built report descriptor covering two HID usage pages at once - Consumer Control for media and volume, Telephony Device for call actions - so a single connection sends both a "next track" and a "reject call" style command. Each of the five buttons runs its own tap/hold gesture state machine with tuned debounce timing, idle windows, and escalating hold thresholds: a single tap plays or pauses, two taps mute, three-plus taps trigger the phone's voice assistant, and a four-second hold blanks the screen, among other gestures, so five physical buttons cover roughly twenty distinct actions without a mode-switch menu. For calls specifically, we integrated Apple's ANCS as a GATT client, discovering it on each new connection and subscribing to the Notification Source characteristic to catch "Incoming Call" notifications directly from iOS, tracking the notification's UID so the firmware can tell an active call from a stale one and reliably detect when a call is answered or ends elsewhere; while a call is ringing or active, the same three buttons automatically remap from media controls to answer, reject, and mic-mute. A round ST7735R display driven through LVGL shows the current action, song info pushed from the phone, volume level, and lock/blackout state, with dedicated screen-lock and screen-blackout modes triggered by their own gestures to save power and prevent pocket presses. Time comes from either the phone's Current Time Service or a custom GATT service we wrote for a companion app to push time directly, and every one of the roughly twenty documented gestures across the five buttons was written up with its expected log output and HID code so cross-platform behavior differences could be tracked systematically, since iOS, Android, and even individual apps like Spotify versus YouTube accept different subsets of the standard HID media and telephony usages.

Results

The result is a five-button remote that punches well above its physical control count: play/pause, mute, voice assistant, seek, track navigation, volume, call answer/reject/mute, redial, screen lock, and screen blackout, without ever needing more than a hold or a multi-tap. The ANCS integration gives it something most HID-only remotes can't do on iOS - real awareness of when a call is actually ringing or active, not just a blind button-to-HID-code mapping, so the same three buttons intelligently mean different things during a call. And because we tested and documented exactly which commands each platform and app actually honor, not just which ones the firmware successfully transmits, the team has a clear, evidence-based picture of the product's real-world behavior instead of one built on assumptions about how phones handle BLE HID.

Contact Us

Kick-start your project

Get in touch with our team to discuss your business needs and see how we can help with a project like this one.