Skip to content

BCM4500 Demodulator Interface

The Broadcom BCM4500 is a 128-pin MQFP satellite demodulator that handles RF demodulation, forward error correction, and MPEG-2 transport stream output. The FX2 communicates with it exclusively over the shared I2C bus using an indirect register protocol.

See the Register Map for a consolidated lookup of all BCM4500 and FX2 register addresses referenced on this page.

ParameterValue
7-bit I2C address0x08
8-bit write address0x10
8-bit read address0x11
Bus speed400 kHz
FX2 I2C controller registersI2CS (0xE678), I2DAT (0xE679), I2CTL (0xE67A)
Alternate probe addresses (v2.13)0x3F, 0x7F

The custom firmware and kernel driver use the 7-bit address 0x08. The stock firmware writes addr << 1 = 0x10 for write and (addr << 1) | 1 = 0x11 for read, following standard I2C convention.

These registers are accessed via standard I2C write/read to the BCM4500’s device address:

RegisterFunctionUsed By
0xA2Status register (polled for readiness during boot)Boot probe, signal strength
0xA4Lock/ready register; bit 5 (0x20) = signal lockedSignal lock check
0xA6Indirect page/address selectIndirect register protocol
0xA7Indirect data register (read/write)Indirect register protocol
0xA8Indirect command registerIndirect register protocol
0xF9Demod status (v2.13 only)GET_DEMOD_STATUS (0x99) / INT0 polling

The BCM4500 uses an indirect register access scheme through three directly-addressable registers (0xA6, 0xA7, 0xA8). All tuning configuration, initialization data, and signal monitoring are performed through this protocol.

  1. Page select — I2C WRITE to 0x08, register 0xA6 with the page number (typically 0x00).

  2. Data write — I2C WRITE to 0x08, register 0xA7 with N data bytes. The auto-increment feature allows writing multiple bytes in a single I2C transaction.

  3. Execute — I2C WRITE to 0x08, register 0xA8 with value 0x03 (indirect write command).

  4. Poll completion — I2C READ register 0xA8 until bit 0 clears (command complete).

  5. Verify — Optionally I2C READ register 0xA7 to read back and compare.

Indirect Write Protocol
// Step 1: Page select
I2C WRITE: [START] [0x10] [0xA6] [0x00] [STOP]
// Step 2: Data write (multi-byte, auto-increment)
I2C WRITE: [START] [0x10] [0xA7] [data0] [data1] ... [dataN] [STOP]
// Step 3: Execute indirect write
I2C WRITE: [START] [0x10] [0xA8] [0x03] [STOP]
// Step 4: Poll until complete
I2C READ: [START] [0x10] [0xA8] [Sr] [0x11] [result] [STOP]
// Repeat until (result & 0x01) == 0
  1. Address select — I2C WRITE to 0x08, register 0xA6 with the target register address.

  2. Placeholder write — I2C WRITE to 0x08, register 0xA7 with value 0x00.

  3. Execute — I2C WRITE to 0x08, register 0xA8 with value 0x01 (indirect read command).

  4. Wait — Short delay (~1 ms) for the BCM4500 to fetch the data.

  5. Read result — I2C READ from 0x08, register 0xA7 to get the result byte.

The BCM4500’s data register (0xA7) supports auto-increment for multi-byte writes within a single I2C transaction. When writing N data bytes to 0xA7 without issuing STOP between bytes, the BCM4500 internally advances its data buffer pointer:

I2C transaction (single write, multiple data bytes):
START -> 0x10 (write) -> 0xA7 (reg) -> data[0] -> data[1] -> ... -> data[N-1] -> STOP

The firmware uses this for initialization blocks and tuning data, reducing I2C bus overhead compared to byte-by-byte writes.

The stock firmware uses a specific pattern for writing initialization blocks, extracted from FUN_CODE_0ddd:

Init Block Write Sequence
// 1. Page select = 0
I2C WRITE: [0x10] [0xA6] [0x00]
// 2. Multi-byte data (auto-increment)
I2C WRITE: [0x10] [0xA7] [data0] [data1] ... [dataN]
// 3. Trailing zero (stock firmware quirk)
I2C WRITE: [0x10] [0xA7] [0x00]
// 4. Commit indirect write
I2C WRITE: [0x10] [0xA8] [0x03]
// 5. Poll for completion
I2C READ: [0xA8] until bit 0 clear

The tune function wraps the BCM4500 I2C programming sequence in a two-level retry loop:

  • Inner loop: tries up to 3 different I2C address configurations per attempt. This supports hardware variants where the BCM4500 may appear at different bus addresses.
  • Outer loop: retries the entire inner scan up to 3 times.

This yields up to 3 × 3 = 9 total I2C programming attempts per tune command. The v2.13 firmware adds a 20-attempt retry with checksum verification on each individual I2C write within the programming step.

The v2.13 firmware repurposed the INT0 interrupt handler (vector at CODE:0003) from USB re-enumeration to demodulator availability detection. The handler runs once during boot, before the main loop:

INT0 handler (v2.13) — demod probe
void INT0_vector(void) {
for (counter = 0x28; counter != 0; counter--) { // 40 iterations
byte result = I2C_read(0x7F); // Probe first alternate address
if (result != 0x01) {
result = I2C_read(0x3F); // Probe second alternate address
if (result != 0x01) break; // Got a response — demod present
}
}
no_demod_flag = (counter == 0); // True if all 40 attempts failed
}

If neither address responds after 40 iterations, no_demod_flag is set. This flag causes the firmware to skip all tuning attempts, avoiding I2C bus hangs on boards where the demodulator is absent or unpopulated.

When the boot probe fails (all 40 attempts exhausted):

  1. no_demod_flag is set to a non-zero value
  2. The firmware enters its normal main loop but skips BCM4500 initialization
  3. TUNE_8PSK (0x86) commands are accepted but silently fail (no I2C transactions issued)
  4. GET_SIGNAL_LOCK (0x90) returns 0x00 (unlocked)
  5. The device remains functional for USB communication but cannot tune

This graceful degradation allows the host software to detect the condition via persistent lock failure rather than USB timeouts.

The BCM4500 contains two FEC decoder paths:

Advanced Modulation Turbo FEC Decoder

Iterative turbo code decoder with the following code rates:

ModulationSupported Rates
QPSK1/4, 1/2, 3/4
8PSK2/3, 3/4, 5/6, 8/9
16QAM3/4

Outer code: Reed-Solomon (t=10).

These turbo codes are Broadcom/EchoStar proprietary and are not part of any open standard. They were used by Dish Network for high-definition satellite broadcasts.

The firmware uses a 10-entry dispatch table for modulation types. See Tuning Protocol for the full tuning sequence.

IndexModulationFEC Path
0DVB-S QPSKLegacy (Viterbi + RS)
1Turbo QPSKTurbo
2Turbo 8PSKTurbo
3Turbo 16QAMTurbo
4DCII ComboLegacy
5DCII I-streamLegacy
6DCII Q-streamLegacy
7DCII Offset QPSKLegacy
8DSS QPSKLegacy (Viterbi + RS)
9DVB-S BPSKLegacy (Viterbi + RS)

Indices 8 and 9 (DSS and DVB BPSK) share the same firmware handler. The FEC lookup uses the same table as DVB-S QPSK but ORs the result with 0x80 to distinguish them.