# Anatomy of a USB Power Delivery PDO

> How a USB-C charger declares what it can supply: the 32 bits of the Power Data Object, the field scaling, and the sink↔source negotiation that takes you from the initial 5 V to the power contract.

Published: 2026-06-23
Updated: 2026-08-25
Practice: elettronica
Standard: Anatomy of a USB Power Delivery PDO <https://www.usb.org/document-library/usb-power-delivery>
Repository: <https://github.com/stefanofante/USBPD-Stack>

Page: <https://www.stline.it/en/wiki/usb-pd-pdo/>

---

When you plug a phone into a USB-C charger, before a single milliampere flows beyond the safe 5 V the two devices talk to each other. The charger declares what it can supply, the device chooses, and only then does the voltage rise. That declaration is a list of **Power Data Objects** (PDOs): 32-bit words, each one a power profile. This tool decodes and builds them; this page explains how they are made.

## What a PDO is

A **Power Data Object** is a 32-bit word that describes *one* way a source can supply power. A charger does not offer a single profile but a list — its *Source Capabilities* — typically one to seven PDOs: 5 V, 9 V, 15 V, 20 V, perhaps a programmable profile. The receiving device (the *sink*) reads the list and asks for what it needs.

The basic rule, set by the specification: the **first PDO is always 5 V Fixed**, and the subsequent Fixed PDOs are in increasing voltage. This is what guarantees that any device, even the simplest, always finds the 5 V to start from.

## The five types

The **bits 30–31** of every PDO declare its type. They are the first thing to read, because they determine how to interpret all the other bits:

- **Fixed Supply** (`00`) — fixed voltage, maximum current. It is the classic profile: "5 V up to 3 A", "20 V up to 5 A".
- **Battery** (`01`) — a battery source, expressed as a voltage range and maximum **power**.
- **Variable Supply** (`10`) — unregulated variable voltage, expressed as a voltage range and maximum current.
- **Augmented PDO / APDO** (`11`) — the "smart" profiles introduced by the more recent revisions. A further subtype field (bits 28–29) distinguishes:
  - **SPR PPS** — *Programmable Power Supply*: the voltage adjusts continuously within a range, for adaptive charging.
  - **EPR AVS** — *Adjustable Voltage Supply*: the high-power profile (above 100 W) of the Extended Power Range.

## Field scaling: the unit trap

This is the most common mistake when reading a PDO by hand. The fields do not contain volts and amperes: they contain **integers**, and each PDO type uses a different scale factor. Getting the factor wrong means reading "5 V" where there are "10 V".

For **Fixed, Variable and Battery** PDOs:

$$
\begin{array}{lcl}
\text{Voltage: } 50\,\text{mV/unit} & \rightarrow & \text{value}\times 0.05 = \text{V} \\[4pt]
\text{Current: } 10\,\text{mA/unit} & \rightarrow & \text{value}\times 0.01 = \text{A} \\[4pt]
\text{Power: } 250\,\text{mW/unit} & \rightarrow & \text{value}\times 0.25 = \text{W} \quad (\text{Battery only})
\end{array}
$$

A Fixed PDO of 5 V / 3 A therefore carries the number **100** in the voltage field (100 × 50 mV = 5 V) and **300** in the current field (300 × 10 mA = 3 A).

For **APDOs** (PPS and AVS) the scaling **changes**, and this is the second classic stumble:

$$
\begin{array}{lcl}
\text{Voltage: } 100\,\text{mV/unit} & \rightarrow & \text{value}\times 0.1 = \text{V} \\[4pt]
\text{Current: } 50\,\text{mA/unit} & \rightarrow & \text{value}\times 0.05 = \text{A}
\end{array}
$$

Same bit, different meaning depending on the type: this is why a decoder must always read the bits 30–31 *first*, and only then interpret the rest.

## The bit-by-bit structure

For each PDO, the tool shows a map of the 32 bits with the fields highlighted. The Fixed PDO is the one you meet most often, and its **complete** map is below — all thirty-two bits accounted for, with no gaps:

| Bits | Field | Meaning |
|---|---|---|
| 31–30 | PDO type | `00` = Fixed |
| 29 | Dual-Role Power | can both source and sink |
| 28 | USB Suspend Supported | honours USB suspend |
| 27 | Unconstrained Power | unconstrained supply (mains) |
| 26 | USB Comms Capable | speaks USB, not only power |
| 25 | Dual-Role Data | can be host or device |
| 24 | Unchunked Ext Msg | extended messages without chunking |
| 23 | EPR Mode Capable | can enter EPR mode |
| 22 | Reserved | must be 0 |
| 21–20 | **Peak Current** | **allowed overcurrent — see below** |
| 19–10 | Voltage | 50 mV per unit |
| 9–0 | Max Current | 10 mA per unit |

The eight flag bits (29–22) communicate the device's capabilities, not a power profile: they describe *who* the device is. They are only to be read on the **first** Fixed PDO of the list, where the specification makes them meaningful; in subsequent PDOs they are ignored.

### The bits people forget: Peak Current

Bits **21–20** are the ones summary descriptions skip, and they say something a designer needs: how much **instantaneous overcurrent** the source tolerates beyond the declared maximum, and for how long.

| Code | Allowed overcurrent |
|---|---|
| 00 | 100 % |
| 01 | 110 % / 130 % / 150 % |
| 10 | 125 % / 150 % / 200 % |
| 11 | 150 % / 175 % / 200 % |

The three values in each row correspond to three different time windows (from the very short pulse to the prolonged overload). The practical meaning is that a 3 A PDO with code `11` tolerates peaks up to 6 A for short intervals: decisive information for sizing a sink's input capacitor, or for understanding why a “3 A” charger does not complain at 4.5 A. With code `00` there is no margin at all, and the declared limit is the real one.

### A decoding example

Take the value `0x0002D12C`. Bits 30–31 are `00` → it is a **Fixed PDO**. The voltage field (bits 19–10) holds 180: 180 × 50 mV = **9 V**. The current field (bits 9–0) holds 300: 300 × 10 mA = **3 A**. The PDO therefore declares “9 V up to 3 A”. Building it is the inverse operation: 9 V / 50 mV = 180 in the voltage field, 3 A / 10 mA = 300 in the current field, type `00`.

## PPS and EPR: two different extensions

The two acronyms are often confused, but they answer opposite needs.

**PPS** (*Programmable Power Supply*, from USB-PD 3.0) is used to adjust the voltage **precisely and continuously** within a range, generally below 21 V. It is meant for adaptive charging: the charger follows the battery's charging curve instead of imposing fixed steps. A detail that breeds confusion: the runtime adjustment happens in **20 mV** steps, but the *limits* of the range in the PDO are encoded in **100 mV** steps. These are two different things — the granularity at which you regulate, and the resolution at which the endpoints are declared.

**EPR** (*Extended Power Range*, from USB-PD 3.1) instead serves to go **beyond 100 W**, up to 240 W, introducing Fixed voltages at 28, 36 and 48 V and the **AVS** profile. In AVS the current is not fixed: it varies with the voltage, because the constraint is power. This is why, for AVS profiles, the tool shows the **power** instead of a maximum current — it reflects how the source actually reasons.

### The two APDO layouts do not resemble each other

Saying that “for APDOs the scaling changes” covers the units, but is not enough: PPS and AVS have **completely different field boundaries**, and using one's layout on the other produces plausible, wrong numbers.

| Bits | SPR PPS (subtype 00) | EPR AVS (subtype 01) |
|---|---|---|
| 31–30 | PDO type = `11` | PDO type = `11` |
| 29–28 | subtype = `00` | subtype = `01` |
| 27 | PPS Power Limited | Peak Current |
| 27–26 | — | Peak Current |
| 26–25 | Reserved | — |
| 25–20 | — | Reserved |
| 24–17 | Max Voltage (100 mV/u) | — |
| 19–10 | — | Max Voltage (100 mV/u) |
| 16 | Reserved | — |
| 15–8 | Min Voltage (100 mV/u) | — |
| 9 | — | Reserved |
| 8–0 | — | PDP (1 W/u) |
| 7 | Reserved | — |
| 6–0 | Max Current (50 mA/u) | — |

Two asymmetries. AVS does not encode a minimum voltage: the minimum is fixed by the specification at **15 V** and does not appear in the bits — a tool has to know this, because there is no field to read. And AVS carries no current but the **PDP** (Power Delivery Power) in watts: consistently, the allowed current varies with the chosen voltage.

### The reserved subtypes

The subtype field is **two** bits, so it has four possible values, but R3.1 defines two: `00` SPR PPS and `01` EPR AVS. The values `10` and `11` are **reserved**.

A tool has two ways to behave in front of a reserved subtype, and only one is correct: it can reject the PDO, or decode it *best-effort* with the nearest layout — but in that second case it must declare the field's **true** value in the bit map, marked as reserved. Showing `01 (EPR AVS)` over bits that read `10` would be lying about the bits, which is exactly what a decoder must not do. This tool decodes best-effort and flags the field as *Reserved*.

### How much fits in a field

The fields have a fixed number of bits, hence a ceiling:

| Field | Bits | Step | Maximum expressible value |
|---|---|---|---|
| Fixed — voltage | 10 | 50 mV | 51.15 V |
| Fixed — current | 10 | 10 mA | 10.23 A |
| Battery — power | 10 | 250 mW | 255.75 W |
| PPS — voltage | 8 | 100 mV | 25.5 V |
| PPS — current | 7 | 50 mA | 6.35 A |
| AVS — voltage | 10 | 100 mV | 102.3 V |
| AVS — PDP | 9 | 1 W | 511 W |

The Fixed voltage ceiling — **51.15 V** — sits comfortably above EPR's 48 V, while the current one, **10.23 A**, is why past 5 A you go up in voltage and not in current. The PPS current field is the narrowest of all (7 bits, maximum 6.35 A): PPS and EPR are not overlapping extensions, and this is one of the points where you can see it.

## Negotiation: from PDO to RDO

Decoding the list is only half the work. The living part of the protocol is the **negotiation**: the sink examines the offered PDOs and chooses one, building a **Request Data Object** (RDO) that it sends back to the source. The RDO does not contain a voltage: it contains the **position** of the chosen PDO in the list (the *Object Position*, from 1 to 13 in EPR) plus the requested operating and maximum current.

The selection logic follows a priority: an exact match on a Fixed PDO takes precedence, then the programmable profiles (PPS/AVS) when the voltage falls within their range, finally the fallbacks. If no profile satisfies the request, the sink stays on the safe 5 V. In negotiation mode the tool shows which PDO would be chosen and why, and builds the corresponding RDO.

## The limits of this tool

It is a teaching and working tool, not a conformance validator. It decodes and encodes PDOs and RDOs according to the specification's scaling, but it does **not** verify the packets' CRCs, does **not** simulate the protocol's physical layer (BMC, control messages, timers), and covers the commonly used PDO types — not every corner case of the most recent revisions. The values it produces are bit-accurate for the PDO structure; a real conformance check requires a protocol analyzer and the official specification.

## References

- **USB Implementers Forum (USB-IF)** — [usb.org](https://www.usb.org), the body that publishes and maintains the specification.
- **USB Power Delivery Specification** — the normative document (revisions 3.1 / 3.2), available in the documents area of [usb.org/documents](https://www.usb.org/documents).
- **USBPD-Stack** — our open-source USB Power Delivery stack for the PTN5110 controller, which implements the decoding and negotiation described here: [github.com/stefanofante/USBPD-Stack](https://github.com/stefanofante/USBPD-Stack).
- **Related tool** — the [PDO decoder/encoder](/en/tools/usb-pd-decoder/) puts all this into practice: paste a PDO and see the fields, or build it from values.
