Skip to content

Commit 3f70cbc

Browse files
committed
Improve protocol analyzer
1 parent 644759c commit 3f70cbc

File tree

9 files changed

+184
-80
lines changed

9 files changed

+184
-80
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void setup() {
4747
}
4848

4949
void loop() {
50-
USBPDProtocolAnalyzer::poll();
50+
PDProtocolAnalyzer.poll();
5151
}
5252
```
5353

examples/ProtocolAnalyzer/ProtocolAnalyzer.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ void setup() {
66
}
77

88
void loop() {
9-
ProtocolAnalyzer::poll();
9+
PDProtocolAnalyzer.poll();
1010
}

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"license": "MIT",
1919
"frameworks": ["arduino"],
2020
"platforms": ["ststm32"],
21-
"headers": ["USBPowerDelivery.h", "PDController.h", "PDSink.h", "USBPDProtocolAnalyzer.h"],
21+
"headers": ["USBPowerDelivery.h", "PDController.h", "PDSink.h", "PDProtocolAnalyzer.h"],
2222
"examples": [
2323
{
2424
"name": "Protocol Analyzer",

src/USBPDProtocolAnalyzer.cpp renamed to src/PDProtocolAnalyzer.cpp

Lines changed: 150 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@
77
//
88

99
#include <Arduino.h>
10-
#include "USBPDProtocolAnalyzer.h"
11-
#include "PDSourceCapability.h"
10+
#include "PDProtocolAnalyzer.h"
1211
#include "PDController.h"
1312

14-
1513
static const char* const ControlMessageNames[] = {
1614
[0] = nullptr,
1715
[(int)PDMessageType::controlGoodCrc] = "GoodCRC",
@@ -57,37 +55,6 @@ static const char* const DataMessageNames[] = {
5755
[(int)PDMessageType::dataVendorDefined - 0x80] = "Vendor Defined",
5856
};
5957

60-
static const char* getMessageName(PDMessageType messageType) {
61-
unsigned int index = (unsigned int)messageType;
62-
const char* name = nullptr;
63-
if (index < 0x80) {
64-
constexpr unsigned int arraySize = sizeof(ControlMessageNames) / sizeof(ControlMessageNames[0]);
65-
if (index < arraySize)
66-
name = ControlMessageNames[index];
67-
} else {
68-
index -= 0x80;
69-
constexpr unsigned int arraySize = sizeof(DataMessageNames) / sizeof(DataMessageNames[0]);
70-
if (index < arraySize)
71-
name = DataMessageNames[index];
72-
}
73-
return name != nullptr ? name : "<unknown>";
74-
}
75-
76-
static const char* const SupplyTypeNames[] = {
77-
[(int)PDSupplyType::fixed] = "Fixed",
78-
[(int)PDSupplyType::battery] = "Battery",
79-
[(int)PDSupplyType::variable] = "Variable",
80-
[(int)PDSupplyType::pps] = "PPS",
81-
};
82-
83-
static const char* getSupplyTypeName(PDSupplyType type) {
84-
constexpr unsigned int arraySize = sizeof(SupplyTypeNames) / sizeof(SupplyTypeNames[0]);
85-
if ((unsigned int)type < arraySize)
86-
return SupplyTypeNames[(unsigned int)type];
87-
else
88-
return "<unknown>";
89-
}
90-
9158
static const char* const SOPSequenceNames[] = {
9259
[0] = "INV",
9360
[(int)PDSOPSequence::sop] = "SOP",
@@ -97,33 +64,11 @@ static const char* const SOPSequenceNames[] = {
9764
[(int)PDSOPSequence::sop2Debug] = "SOP2D",
9865
};
9966

100-
static const char* getSOPSequenceName(PDSOPSequence sequence) {
101-
constexpr unsigned int arraySize = sizeof(SOPSequenceNames) / sizeof(SOPSequenceNames[0]);
102-
unsigned int index = (unsigned int)sequence;
103-
if (index >= arraySize)
104-
index = arraySize;
105-
return SOPSequenceNames[index];
106-
}
107-
108-
static const char* getSender(const PDMessage* message) {
109-
auto seq = message->sopSequence;
110-
if (seq == PDSOPSequence::sop) {
111-
return (message->header & 0x0100) != 0 ? "Source" : "Sink";
112-
} else if (seq == PDSOPSequence::sop1 || seq == PDSOPSequence::sop2) {
113-
return (message->header & 0x0100) != 0 ? "Cable" : "Port";
114-
}
11567

116-
return "";
117-
}
68+
USBPDProtocolAnalyzer PDProtocolAnalyzer;
11869

119-
static void printMessage(const PDMessage* message) {
120-
Serial.printf("CC%d %-5s %-7s %-20s %d %04x",
121-
message->cc, getSOPSequenceName(message->sopSequence),
122-
getSender(message),getMessageName(message->type()),
123-
message->messageId(), message->header);
124-
int numObjects = message->numObjects();
125-
for (int i = 0; i < numObjects; i++)
126-
Serial.printf(" %08x", message->objects[i]);
70+
USBPDProtocolAnalyzer::USBPDProtocolAnalyzer() {
71+
memset(&capabilities, 0, sizeof(capabilities));
12772
}
12873

12974
void USBPDProtocolAnalyzer::poll() {
@@ -137,7 +82,6 @@ void USBPDProtocolAnalyzer::poll() {
13782
case PDLogEntryType::messageReceived:
13883
Serial.print("RX: ");
13984
printMessage(logEntry->message);
140-
Serial.println();
14185
break;
14286
case PDLogEntryType::sinkSourceConnected:
14387
Serial.printf("Connected: CC%d", PowerController.ccPin);
@@ -158,7 +102,6 @@ void USBPDProtocolAnalyzer::poll() {
158102
case PDLogEntryType::transmissionStarted:
159103
Serial.print("TX: ");
160104
printMessage(logEntry->message);
161-
Serial.println();
162105
break;
163106
case PDLogEntryType::transmissionCompleted:
164107
Serial.println("TX: completed");
@@ -168,3 +111,149 @@ void USBPDProtocolAnalyzer::poll() {
168111
break;
169112
}
170113
}
114+
115+
void USBPDProtocolAnalyzer::printMessage(const PDMessage* message) {
116+
Serial.printf("CC%d %-5s %-7s %-20s %d %04x",
117+
message->cc, getSOPSequenceName(message->sopSequence),
118+
getSender(message),getMessageName(message->type()),
119+
message->messageId(), message->header);
120+
121+
int numObjects = message->numObjects();
122+
for (int i = 0; i < numObjects; i++)
123+
Serial.printf(" %08x", message->objects[i]);
124+
125+
Serial.println();
126+
127+
if (numObjects > 0) {
128+
switch (message->type()) {
129+
case PDMessageType::dataRequest:
130+
printRequestDetails(message);
131+
break;
132+
case PDMessageType::dataSourceCapabilities:
133+
printCapabilitiesDetails(message);
134+
break;
135+
default:
136+
;
137+
}
138+
}
139+
}
140+
141+
void USBPDProtocolAnalyzer::printCapabilitiesDetails(const PDMessage* message) {
142+
auto numbObjects = message->numObjects();
143+
144+
// remember source capabilities
145+
capabilities.header = message->header;
146+
memcpy(&capabilities.objects, &message->objects, numbObjects * 4);
147+
148+
for (int i = 0; i < numbObjects; i += 1) {
149+
auto object = message->objects[i];
150+
int supplyType = (object >> 30) & 0x03;
151+
152+
Serial.printf(" %2d:", i + 1);
153+
154+
if (supplyType == 0) {
155+
// fixed supply: Vmin = Vmax
156+
int maxCurrent = (object & 0x3ff) * 10;
157+
int maxVoltage = ((object >> 10) & 0x3ff) * 50;
158+
Serial.printf(" Fixed %6dmV (fix) %6dmA (max) ", maxVoltage, maxCurrent);
159+
if ((object & (1 << 24)) != 0) Serial.print("extended msg, ");
160+
if ((object & (1 << 25)) != 0) Serial.print("dual-role data, ");
161+
if ((object & (1 << 26)) != 0) Serial.print("USB comm capable, ");
162+
if ((object & (1 << 27)) != 0) Serial.print("unconstrained power, ");
163+
if ((object & (1 << 28)) != 0) Serial.print("USB suspend, ");
164+
if ((object & (1 << 29)) != 0) Serial.print("dual-role power");
165+
166+
} else if (supplyType == 1) {
167+
// battery
168+
int maxCurrent = (object & 0x3ff) * 10;
169+
int minVoltage = ((object >> 10) & 0x3ff) * 50;
170+
int maxVoltage = ((object >> 20) & 0x3ff) * 50;
171+
Serial.printf(" Battery %6dmV (min) %6dmV (max) %6dmA (max)", minVoltage, maxVoltage, maxCurrent);
172+
173+
} else if (supplyType == 2) {
174+
// variable
175+
int maxPower = (object & 0x3ff) * 250;
176+
int minVoltage = ((object >> 10) & 0x3ff) * 50;
177+
int maxVoltage = ((object >> 20) & 0x3ff) * 50;
178+
Serial.printf(" Variable %6dmV (min) %6dmV (max) %6dmW (max)", minVoltage, maxVoltage, maxPower);
179+
180+
} else {
181+
// APDO
182+
if (((object >> 28) & 0x03) == 0) {
183+
// PPS
184+
int maxCurrent = (object & 0x7f) * 50;
185+
int minVoltage = ((object >> 8) & 0xff) * 100;
186+
int maxVoltage = ((object >> 17) & 0xff) * 100;
187+
Serial.printf(" PPS %6dmV (min) %6dmV (max) %6dmA (max)", minVoltage, maxVoltage, maxCurrent);
188+
}
189+
}
190+
191+
Serial.println();
192+
}
193+
}
194+
195+
void USBPDProtocolAnalyzer::printRequestDetails(const PDMessage* message) {
196+
auto header = message->header;
197+
auto object = message->objects[0];
198+
int objPos = (object >> 28) & 0x07;
199+
bool giveBack = (object & (1 << 27)) != 0;
200+
auto capObject = capabilities.numObjects() >= objPos ? capabilities.objects[objPos - 1] : 0;
201+
int supplyType = (capObject >> 30) & 0x03;
202+
203+
if (supplyType == 0 || supplyType == 2) {
204+
int current0 = (object & 0x3ff) * 10;
205+
int current1 = ((object >> 10) & 0x3ff) * 10;
206+
Serial.printf(" Capability: %d %6dmA (oper) %6dmA (%s) ", objPos, current1, current0, giveBack ? "min" : "max");
207+
208+
} else if (supplyType == 1) {
209+
int power0 = (object & 0x3ff) * 250;
210+
int power1 = ((object >> 10) & 0x3ff) * 250;
211+
Serial.printf(" Capability: %d %6dmW (oper) %6dmW (%s) ", objPos, power1, power0, giveBack ? "min" : "max");
212+
213+
} else {
214+
int current = (object & 0x7f) * 50;
215+
int voltage = ((object >> 9) & 0x7ff) * 20;
216+
Serial.printf(" Capability: %d %6dmV (oper) %6dmA (oper) ", objPos, voltage, current);
217+
}
218+
219+
if ((object & (1 << 23)) != 0) Serial.print("extended msg, ");
220+
if ((object & (1 << 24)) != 0) Serial.print("USB suspend, ");
221+
if ((object & (1 << 25)) != 0) Serial.print("USB comm capable, ");
222+
if (giveBack) Serial.print("give back");
223+
Serial.println();
224+
}
225+
226+
const char* USBPDProtocolAnalyzer::getMessageName(PDMessageType messageType) {
227+
unsigned int index = (unsigned int)messageType;
228+
const char* name = nullptr;
229+
if (index < 0x80) {
230+
constexpr unsigned int arraySize = sizeof(ControlMessageNames) / sizeof(ControlMessageNames[0]);
231+
if (index < arraySize)
232+
name = ControlMessageNames[index];
233+
} else {
234+
index -= 0x80;
235+
constexpr unsigned int arraySize = sizeof(DataMessageNames) / sizeof(DataMessageNames[0]);
236+
if (index < arraySize)
237+
name = DataMessageNames[index];
238+
}
239+
return name != nullptr ? name : "<unknown>";
240+
}
241+
242+
const char* USBPDProtocolAnalyzer::getSOPSequenceName(PDSOPSequence sequence) {
243+
constexpr unsigned int arraySize = sizeof(SOPSequenceNames) / sizeof(SOPSequenceNames[0]);
244+
unsigned int index = (unsigned int)sequence;
245+
if (index >= arraySize)
246+
index = arraySize;
247+
return SOPSequenceNames[index];
248+
}
249+
250+
const char* USBPDProtocolAnalyzer::getSender(const PDMessage* message) {
251+
auto seq = message->sopSequence;
252+
if (seq == PDSOPSequence::sop) {
253+
return (message->header & 0x0100) != 0 ? "Source" : "Sink";
254+
} else if (seq == PDSOPSequence::sop1 || seq == PDSOPSequence::sop2) {
255+
return (message->header & 0x0100) != 0 ? "Cable" : "Port";
256+
}
257+
258+
return "";
259+
}

src/PDProtocolAnalyzer.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// USB Power Delivery for Arduino
3+
// Copyright (c) 2023 Manuel Bleichenbacher
4+
//
5+
// Licensed under MIT License
6+
// https://opensource.org/licenses/MIT
7+
//
8+
9+
#pragma once
10+
11+
#include "PDMessage.h"
12+
13+
struct USBPDProtocolAnalyzer {
14+
USBPDProtocolAnalyzer();
15+
void poll();
16+
17+
private:
18+
void printMessage(const PDMessage* message);
19+
void printCapabilitiesDetails(const PDMessage* message);
20+
void printRequestDetails(const PDMessage* message);
21+
const char* getMessageName(PDMessageType messageType);
22+
const char* getSOPSequenceName(PDSOPSequence sequence);
23+
const char* getSender(const PDMessage* message);
24+
25+
PDMessage capabilities;
26+
};
27+
28+
extern USBPDProtocolAnalyzer PDProtocolAnalyzer;

src/USBPDProtocolAnalyzer.h

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/USBPowerDelivery.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414

1515
#include "PDController.h"
1616
#include "PDSink.h"
17-
#include "USBPDProtocolAnalyzer.h"
17+
#include "PDProtocolAnalyzer.h"

test/ProtocolAnalyzer/src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ void setup() {
1919
}
2020

2121
void loop() {
22-
USBPDProtocolAnalyzer::poll();
22+
PDProtocolAnalyzer.poll();
2323
}

test/VoltageChange/src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void setup() {
3030

3131
void loop() {
3232
PowerSink.poll();
33-
USBPDProtocolAnalyzer::poll();
33+
PDProtocolAnalyzer::poll();
3434

3535
if (isUSBPDSource && hasExpired(nextVoltageChangeTime))
3636
switchVoltage();

0 commit comments

Comments
 (0)