How BLE Coded PHY S=8 Achieves 4x Range at the Cost of 8x Airtime

A standard BLE chip can close a link to a satellite 600 km overhead. Same silicon you’d put in a fitness tracker. No exotic RF, no licensed spectrum, no proprietary modulation. The trick is a single bit in a bt_conn_le_phy_param struct: switch to Coded PHY S=8, and the receiver’s sensitivity floor drops by roughly 12 dB. That’s the difference between “across the room” and “across the sky.”
The catch is airtime. Every bit takes 8x longer to send. Get the tradeoff wrong and your wearable misses scan windows, your gateway can’t keep up with the connection event budget, and your battery dies faster despite the better link budget.
This guide shows the math behind both numbers, the Nordic/Zephyr code to configure it, and when S=8 is actually worth picking over S=2.
What Coded PHY Actually Does
Coded PHY is BLE 5’s forward error correction mode. The radio still keeps the 1 Msym/s rate on air, but each information bit is expanded into either 2 symbols (S=2) or 8 symbols (S=8) through a convolutional coder plus a pattern mapper. The receiver uses the redundancy to recover bits that would otherwise be lost in noise.
S=2 uses convolutional coding alone. S=8 adds a pattern mapper that spreads each coded bit across 4 more symbols, raising the energy per information bit at the receiver.
The packet structure changes too. Coded PHY adds a Coding Indicator (CI) field after the access address, and TERM sequences to flush the convolutional coder state.
1M PHY packet:
[Preamble][Access Addr][PDU.................][CRC]
1B 4B 2-257B 3B
Total: ~80 µs to ~2.1 ms
Coded PHY packet (S=8):
[Preamble][AA-coded][CI][TERM1][PDU+CRC coded x8][TERM2]
80µs 256µs 16µs 24µs variable 24µsThe preamble, access address, CI, and TERM fields always go out at S=8, no matter what S value the payload uses. Only the PDU and CRC use the chosen S value. That fixed ~400 µs overhead matters when we get to the airtime math.
Coded PHY Range Calculation: Where 4x Comes From
The Bluetooth SIG and Nordic’s measured numbers put the sensitivity improvement at roughly:
- S=2: ~6 dB better than 1M PHY
- S=8: ~12 dB better than 1M PHY
Plug that into the Friis equation. Free-space path loss scales as 20·log₁₀(d), so every 6 dB of extra link budget doubles range. 12 dB quadruples it. In environments with higher path loss exponents (suburban, indoor), the gain shrinks because path loss grows faster with distance.
A worked example with a typical nRF52840 at +8 dBm TX:
1M PHY S=2 S=8
TX power +8 dBm +8 +8
RX sensitivity -95 dBm -101 -107
Link budget 103 dB 109 115
Range (n=2, LOS) 1.0x 2.0x 4.0x
Range (n=3, sub) 1.0x 1.6x 2.5x
Range (n=4, ind) 1.0x 1.4x 2.0xIf your 1M PHY baseline measures 100m line-of-sight, S=8 gets you to ~400m in the same environment. Through a couple of concrete walls, that 4x can collapse to 2x or less. Path loss exponent dominates the result. If you haven’t measured n for your deployment, your range prediction is a guess.
One more note: the +12 dB applies on the downlink path the device receives. Coded PHY is symmetric, so the device’s transmissions also reach a coded-capable receiver 12 dB further away. Hubble’s satellite case exploits this on the uplink. The satellite contributes large antenna gain to close the rest of the budget.
BLE S2 vs S8 Airtime: Where 8x Comes From
Airtime for a Coded PHY packet is:
T_packet = T_overhead + (payload_bits × S) / 1 Mbps
T_overhead ≈ 400 µs (preamble + AA + CI + TERMs)For a 27-byte connection PDU (216 bits including headers and CRC):
1M PHY: ~328 µs
S=2: 400 + (216 × 2) = 832 µs (~2.5x)
S=8: 400 + (216 × 8) = 2128 µs (~6.5x)For larger payloads the overhead becomes a smaller share and the ratio approaches the asymptotic 8x. A 255-byte extended advertising payload at S=8 takes roughly 2.7 ms vs ~330 µs at 1M.
Airtime for 27-byte PDU (µs):
1M | ████ 328
S=2 | ██████████ 832
S=8 | ██████████████████████████ 2128The downstream effects:
Connection event capacity drops. A 7.5 ms minimum connection interval that fits 20 packets at 1M PHY fits 3 at S=8.
Scan windows must lengthen. A scanner running 30 ms windows at 1M PHY catches most advertisements. At S=8 with the same advertising interval, you need scan windows on the order of the advertising PDU duration (~2-3 ms minimum just to demodulate one packet) plus margin. Coded PHY scanning at standard duty cycles burns more receiver-on time, which usually dominates the battery budget on a gateway.
Energy per packet rises ~8x. Peak TX current is unchanged, but you’re transmitting for 8x longer. Average current depends on duty cycle and retry behavior. If you were retrying 5x at 1M PHY because of marginal SNR, a single successful S=8 transmission can come out ahead. If your link was already healthy at 1M, switching to S=8 strictly costs you energy.
Configuring Coded PHY in Zephyr
Two snippets cover most cases. On an active connection, request Coded PHY with the S=8 option:
struct bt_conn_le_phy_param phy = {
.options = BT_CONN_LE_PHY_OPT_CODED_S8,
.pref_tx_phy = BT_GAP_LE_PHY_CODED,
.pref_rx_phy = BT_GAP_LE_PHY_CODED,
};
bt_conn_le_phy_update(conn, &phy);For extended advertising on Coded PHY:
struct bt_le_adv_param adv_param = BT_LE_ADV_PARAM_INIT(
BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_CODED,
BT_GAP_ADV_SLOW_INT_MIN,
BT_GAP_ADV_SLOW_INT_MAX,
NULL);Kconfig flags you’ll need:
CONFIG_BT_EXT_ADV=y
CONFIG_BT_CTLR_PHY_CODED=y
CONFIG_BT_PHY_UPDATE=yThree gotchas worth knowing:
BT_CONN_LE_PHY_OPT_CODED_S8is a hint. The controller may negotiate down to S=2 if the peer prefers it. Confirm the actual PHY in thele_phy_updatedcallback.- The scanner side must also be on Coded PHY. Use
BT_LE_SCAN_OPT_CODEDwhen starting the scanner, or it’ll be completely deaf to Coded advertisements. - Coded PHY advertising can only run on the secondary channels via extended advertising. Legacy advertising on the primary channels stays at 1M.
For a working starting point, the Hubble device SDK and Zephyr reference application show Coded PHY configured for the satellite uplink case, including the encryption and packet framing.
When S=8 Is Worth It: The Hubble Case
Hubble Network has demonstrated BLE packets received from LEO satellites at roughly 600 km using off-the-shelf BLE silicon. Closing that link requires every dB the spec offers: S=8 on the device side, plus large antenna gain at the satellite. At 1M PHY the same link is ~12 dB short and doesn’t close. The trick is asymmetric: the device doesn’t know it’s talking to a satellite. It’s just a standard BLE 5 transmission. Hubble’s satellite SDK documentation covers the duty-cycle and payload constraints that make this practical for low-rate telemetry.
For terrestrial designs the same logic applies in miniature. Reach for S=8 when:
- The link has a hard sensitivity floor you can’t budge (deep basement, body-worn through tissue, an asset tracker with no nearby gateways).
- Telemetry is low-rate. A few bytes per minute is fine; a stream of sensor samples isn’t.
- You’re TX-power-limited by regulation or thermal budget and need the gain to come from the receiver side.
Default to S=2 for everything else. It buys you 2x range for 2x airtime, which is a much easier tradeoff to swallow.
Run the Numbers Before the Design Review
Quick filter for the next design review:
- Payload < 30 B, advertising 1x/min or slower → S=8 viable
- Payload > 100 B or update rate > 1 Hz → S=2 maximum, possibly stay on 1M
- Battery-critical wearable with frequent retries on 1M → measure both before committing
- Coexisting with non-Coded scanners (phones, legacy gateways) → S=8 packets are invisible to them; you’ll need a 1M fallback advertising set
- Targeting Hubble’s satellite network → S=8 is required, see the terrestrial transmission guidance for duty-cycle limits
Run the link budget for your TX power and target distance, then run the airtime calculation for your packet size and update rate. If both fit, the PHY choice is made. If only one fits, the requirements need to change before the radio config does.
Hubble Network’s satellite BLE service receives S=8 Coded PHY advertisements directly from devices, eliminating the need for terrestrial gateways in remote deployments. See the transmission specs →