PIC16F1704 — I2C Bridge Controller
PIC16F1704 microcontroller used as an I2C bridge in Antminer hash boards — protocol specification, command reference, and troubleshooting procedures.
Overview
The PIC16F1704 is a Microchip PIC microcontroller used in Antminer hash boards as an I2C bridge between the control board and the hash board's on-board peripherals. It sits on the main I2C bus (accessible from the control board via the signal connector) and provides bridged access to devices on the hash board's internal I2C bus, including temperature sensors (LM75A, NCT218) and the AT24C02 EEPROM.
The PIC acts as a protocol translator — it receives commands from the control board in a custom packet format, executes the corresponding I2C transactions on the internal bus, and returns the results. This architecture isolates the hash board's I2C bus from the control board's bus, preventing bus contention and allowing the PIC to manage timing-sensitive operations like voltage enable sequencing.
Specifications
| Parameter | Value |
|---|---|
| Manufacturer | Microchip |
| Core | PIC (8-bit RISC) |
| Flash Memory | 4 KB |
| RAM | 512 bytes |
| Max Clock | 32 MHz (internal oscillator) |
| I2C | MSSP module (master and slave capable) |
| Supply Voltage | 2.3V to 5.5V |
| Package | SOIC-14, TSSOP-14, QFN-16 |
| I2C Address | 0x20-0x27 (shifts across resets) |
I2C Address Behavior
Critical: The PIC16F1704 I2C address is not fixed. It can appear at any address in the range 0x20 to 0x27, and the address may change after a power cycle or reset. The EEPROM address shifts in sync, maintaining a fixed offset of +0x30 (e.g., PIC at 0x21 means EEPROM at 0x51).
When initializing communication with a hash board, always scan the full 0x20-0x27 range to locate the PIC. Do not hard-code a single address.
| PIC Address | EEPROM Address |
|---|---|
| 0x20 | 0x50 |
| 0x21 | 0x51 |
| 0x22 | 0x52 |
| 0x23 | 0x53 |
| 0x24 | 0x54 |
| 0x25 | 0x55 |
| 0x26 | 0x56 |
| 0x27 | 0x57 |
Communication Protocol
The PIC uses a custom packet-based protocol over I2C. The control board writes command packets to the PIC, waits for processing, then reads response packets.
Packet Format
Transmit (Control Board to PIC):
[55 AA] [LEN] [CMD] [param1] [param2] ... [CHECKSUM]Receive (PIC to Control Board):
[LEN] [CMD] [STATUS] [data1] [data2] ... [CHECKSUM]Field Descriptions
| Field | Size | Description |
|---|---|---|
| Sync | 2 bytes | 0x55 0xAA — marks the start of a command packet |
| LEN | 1 byte | Total packet length from LEN to CHECKSUM (inclusive) |
| CMD | 1 byte | Command code |
| STATUS | 1 byte | Response status (0x01 = success in most commands) |
| Params/Data | N bytes | Command-specific parameters or response data |
| CHECKSUM | 1 byte | Sum of all bytes from LEN to last param/data byte, masked to 8 bits (& 0xFF) |
Checksum Calculation
The checksum covers all bytes from LEN to the last parameter byte (not including the sync bytes 55 AA):
def calculate_checksum(packet_without_sync):
"""Calculate PIC protocol checksum.
packet_without_sync: bytes from LEN to last param (before checksum)
"""
return sum(packet_without_sync) & 0xFF
# Example: CMD 0x15 (voltage enable), params [0x01, 0x00]
# Packet: [55 AA] [05] [15] [01] [00] [checksum]
# LEN=0x05, CMD=0x15, param1=0x01, param2=0x00
# Checksum = (0x05 + 0x15 + 0x01 + 0x00) & 0xFF = 0x1BCommand Reference
CMD 0x15 — Voltage Enable
Enables or disables the hash board voltage rails. This is the primary command used during initialization to power on the ASIC chips.
Transmit:
[55 AA] [05] [15] [enable] [0x00] [checksum]| Parameter | Value | Description |
|---|---|---|
| enable | 0x01 | Enable voltage output |
| enable | 0x00 | Disable voltage output |
Response:
[05] [15] [STATUS] [00] [checksum]CMD 0x15 is the confirmed voltage enable command. Earlier documentation incorrectly listed CMD 0x04 as the voltage enable command, but testing has confirmed 0x15 is correct.
CMD 0x16 — Status Query
Reads the current status of the hash board (voltage state, fault flags).
Transmit:
[55 AA] [03] [16] [checksum]Response:
[06] [16] [STATUS] [data1] [data2] [checksum]Typical successful response: 06 16 01 00 00 1D
CMD 0x3C — Sensor Read
Reads data from a device on the hash board's internal I2C bus (temperature sensors, EEPROM).
Transmit:
[55 AA] [06] [3C] [target_addr] [nbytes] [register] [checksum]| Parameter | Description |
|---|---|
| target_addr | I2C address of the target device (e.g., 0x48 for LM75A) |
| nbytes | Number of bytes to read from the target |
| register | Register address to read from on the target device |
Response:
[LEN] [3C] [STATUS] [byte1] [byte2] ... [checksum]Example — Read temperature from LM75A at 0x48:
# TX: Read 2 bytes from register 0x00 at device 0x48
tx = bytes([0x55, 0xAA, 0x06, 0x3C, 0x48, 0x02, 0x00])
checksum = (0x06 + 0x3C + 0x48 + 0x02 + 0x00) & 0xFF # = 0x8C
tx += bytes([checksum])
# Wait 50ms for PIC to complete the I2C transaction
time.sleep(0.05)
# RX: [07] [3C] [01] [temp_msb] [temp_lsb] [checksum]
# temp_msb=0x19, temp_lsb=0x00 → 25.0°CCMD 0x3B — Sensor Read (Alternate)
An alternate sensor read command observed in sniffed I2C traffic.
Transmit:
[55 AA] [06] [3B] [target_addr] [0x00] [0x00] [checksum]CMD 0x07 — Date Read
Reads the manufacturing date or calibration date stored in the PIC's internal memory.
Transmit:
[55 AA] [03] [07] [checksum]DANGER: Reading more than 2 bytes from CMD 0x07 can hang the PIC, requiring a hardware reset via the RST_N pin. Limit reads to exactly 2 bytes and implement a timeout. If the PIC becomes unresponsive after a CMD 0x07 call, toggle RST_N LOW for 10ms then HIGH to reset it.
CMD 0x06 — Hardware Info
Reads hardware version and configuration information.
Transmit:
[55 AA] [03] [06] [checksum]Critical: Byte-by-Byte I2C Reads
The PIC16F1704 requires byte-by-byte I2C reads. Each response byte must be read as a separate I2C transaction with its own Start condition, address byte, NACK, and Stop condition.
Multi-byte reads (reading N bytes in a single I2C transaction) cause a shift register underrun in the PIC, resulting in bit-shifted garbage data. This is a hardware limitation of the PIC's MSSP module when operating as an I2C slave.
Correct (byte-by-byte):
response = []
for i in range(expected_length):
i2c_start()
i2c_write(pic_addr << 1 | 1) # Read mode
byte = i2c_read_nack() # Read one byte, NACK
i2c_stop()
response.append(byte)Incorrect (multi-byte — will produce garbage):
# DO NOT DO THIS
i2c_start()
i2c_write(pic_addr << 1 | 1)
for i in range(expected_length - 1):
response.append(i2c_read_ack()) # ACK to continue
response.append(i2c_read_nack()) # NACK to end
i2c_stop()Initialization Sequence
The standard initialization sequence for communicating with a hash board via the PIC bridge:
Scan for PIC Address
Scan I2C addresses 0x20 through 0x27. The first address that ACKs is the PIC.
Dump EEPROM
Calculate EEPROM address (PIC address + 0x30). Use CMD 0x3C to read the EEPROM contents for board identification.
Read Date (CMD 0x07)
Read the manufacturing/calibration date. Limit to 2 bytes. Implement a 100ms timeout.
Read Hardware Info (CMD 0x06)
Read the hardware version and configuration.
Enable Voltage (CMD 0x15)
Send CMD 0x15 with enable=0x01 to power on the ASIC voltage domains. Wait 500ms for voltage rails to stabilize before proceeding with ASIC enumeration.
Begin Sensor Monitoring
Start periodic temperature sensor reads using CMD 0x3C, targeting the LM75A or NCT218 sensors at their respective addresses.
Common Failure Modes
1. PIC Not Responding
Symptoms: No device found at any address in the 0x20-0x27 range during I2C scan. Hash board appears completely dead to the control board.
Causes:
- Failed PIC16F1704 IC
- Missing 3.3V power supply (check LDO regulator)
- Broken I2C SDA or SCL trace from the connector to the PIC
- PIC hung from a previous CMD 0x07 failure — try RST_N reset before assuming IC failure
Diagnosis:
- Verify 3.3V at the PIC's VDD pin
- Check SDA and SCL lines for stuck-LOW condition
- Toggle RST_N (if accessible) to attempt a reset
- If power and bus are good but PIC still does not respond, the IC has failed
2. Wrong I2C Address After Reset
Symptoms: PIC was at 0x20, after a reset it is now at 0x23. Software that hard-coded the previous address fails.
Causes: Normal behavior — the PIC address is not persistent across resets.
Fix: Always scan the full 0x20-0x27 range after any reset or power cycle. Never hard-code the PIC address.
3. Checksum Errors in Responses
Symptoms: Received data has incorrect checksums, or data appears garbled.
Causes:
- Multi-byte I2C reads (see the byte-by-byte requirement above)
- I2C bus noise from high-current switching on the board
- Marginal pull-up resistor values on the I2C bus
Fix: Ensure byte-by-byte reads. Add proper decoupling capacitors near the PIC. Verify I2C pull-up resistors are present and within the correct range (typically 4.7K to 10K ohms).
4. Sensor Reads Return Stale Data
Symptoms: Temperature readings do not change, or all sensors return the same value.
Causes:
- PIC is not completing the internal I2C transaction (internal bus issue)
- Target sensor has failed (PIC returns cached or default data)
- Insufficient wait time between CMD 0x3C and reading the response (need at least 50ms)
Fix: Increase the delay after CMD 0x3C to 100ms. Test sensors individually to identify which one is failing. Check the PIC's internal I2C bus (SDA/SCL between PIC and sensors) for continuity.
Replacement Notes
- The PIC16F1704 in SOIC-14 or TSSOP-14 is straightforward to desolder and replace with hot air
- The replacement PIC must be programmed with the correct firmware before installation — a blank PIC will not function as an I2C bridge
- PIC firmware is typically locked (code protection enabled) — you cannot read the firmware from a working PIC to copy it to a replacement
- Sources for programmed replacement PICs: donor boards (salvaged from other failed hash boards with different failures), aftermarket suppliers
- After installation, verify the PIC responds on I2C (scan 0x20-0x27) and can execute CMD 0x16 (status query)
Found In These Miners
- Antminer S19 — 1 per hash board
- Antminer S19 Pro — 1 per hash board
- Antminer S19 XP — 1 per hash board
- Antminer S21 — 1 per hash board
- Antminer S9 — 1 per hash board (older PIC variant)
Related Pages
- AT24C02 EEPROM (accessed via PIC bridge)
- LM75A Temperature Sensor (accessed via CMD 0x3C)
- NCT218 Temperature Sensor (accessed via CMD 0x3C)
- Temperature Sensors Overview
- Hashboard Connectors & Pinouts (I2C bus to PIC)
- UART, SPI & I2C Explained
- How Hash Boards Work
AT24C02 EEPROM — Board Identification Memory
AT24C02 EEPROM specifications, I2C interface, data layout, and troubleshooting for hash board identification and calibration storage in mining hardware.
Hashboard Connectors & Pinouts
Connectors used in ASIC mining hardware — signal connectors, power connectors, pinouts by manufacturer, and common failure modes.