30#include "../../../SensorBuildOpt.h"
31#if !SENSORLIB_EXCLUDE_PMIC_AXP517
35#include "../../../platform/SensorLibLog.hpp"
41static constexpr uint8_t MSG_SOURCE_CAP = 0x01;
42static constexpr uint8_t MSG_REQUEST = 0x02;
43static constexpr uint8_t MSG_ACCEPT = 0x03;
44static constexpr uint8_t MSG_REJECT = 0x04;
45static constexpr uint8_t MSG_PS_RDY = 0x06;
47#if defined(INPUT_PULLUP)
48static constexpr uint8_t IRQ_INPUT_MODE = INPUT_PULLUP;
50static constexpr uint8_t IRQ_INPUT_MODE = INPUT;
52static constexpr uint8_t IRQ_INPUT_MODE = 0;
54static constexpr uint8_t IRQ_ACTIVE_LOW = 0;
55static constexpr uint8_t MAX_TX_RETRY = 100;
56static constexpr uint16_t ACTIONABLE_ALERT_MASK =
66static bool configureSinkRx(
AXP517Pd &pd)
74 : _tcpc(tcpc), _pd(pd)
86 _tcpc.
pinMode(
static_cast<uint8_t
>(_irqPin), IRQ_INPUT_MODE);
107 if (!configureSinkRx(_pd)) {
138 if (!
initSink(_irqPin))
return false;
144 if (!configureSinkRx(_pd)) {
153 uint16_t pending = 0;
154 if (_tcpc.
readAlert(pending) && pending) {
156 if (!
handleIrq(req, event, outCaps))
return false;
160 uint32_t deadline = _tcpc.
millis() + timeoutMs;
161 while (_tcpc.
millis() < deadline) {
162 if (_tcpc.
digitalRead(
static_cast<uint8_t
>(_irqPin)) == IRQ_ACTIVE_LOW) {
164 if (!
service(req, event, outCaps))
return false;
183 if (_tcpc.
digitalRead(
static_cast<uint8_t
>(_irqPin)) != IRQ_ACTIVE_LOW) {
188 if (!
handleIrq(req, outEvent, outCaps))
return false;
189 if (
isDone())
return true;
192 if (!_tcpc.
readAlert(alert))
return false;
193 if (alert == 0)
break;
194 if ((alert & ACTIONABLE_ALERT_MASK) == 0)
break;
195 if (_tcpc.
digitalRead(
static_cast<uint8_t
>(_irqPin)) != IRQ_ACTIVE_LOW)
break;
213 if (!_tcpc.
readAlert(alert))
return false;
214 if (alert == 0)
return true;
216 uint16_t clearMask = alert &
~AXP517Tcpc::AlertRxStatus;
217 if (clearMask && !_tcpc.
clearAlert(clearMask))
return false;
261 if (++_txRetry >= MAX_TX_RETRY) {
272 if (++_txRetry >= MAX_TX_RETRY) {
284 if (!rxOk)
return true;
287 uint8_t msgType = hdr.
msgType();
290 if (msgType == MSG_SOURCE_CAP && objCount > 0) {
298 if (outCaps) *outCaps = caps;
309 }
else if (_state ==
State::WaitAccept && msgType == MSG_ACCEPT && objCount == 0) {
314 }
else if (_state ==
State::WaitAccept && msgType == MSG_REJECT && objCount == 0) {
317 }
else if (_state ==
State::WaitPsRdy && msgType == MSG_PS_RDY && objCount == 0) {
331 if (hdr.
msgType() != MSG_SOURCE_CAP || hdr.
objCount() == 0)
return false;
336 uint8_t parseCount =
static_cast<uint8_t
>(rx.
payloadLen / 4);
338 if (parseCount > 7) parseCount = 7;
340 for (uint8_t
i = 0;
i < parseCount; ++
i) {
347 offer.
maMax = fixed.ma;
381 outOffer = caps.
fixed[0];
390 if (!_tcpc.
clearTx())
return false;
392 return sendRequest(offer, req);
395bool AXP517PdNegotiator::sendRequest(
const FixedOffer &offer,
const RequestParams &req)
397 uint16_t opMa = req.opMa ? req.opMa : offer.maMax;
398 if (offer.maMax && opMa > offer.maMax) opMa = offer.maMax;
400 uint16_t maxMa = req.maxMa ? req.maxMa : opMa;
401 if (offer.maMax && maxMa > offer.maMax) maxMa = offer.maMax;
404 req.capMismatch, req.usbCommCapable,
406 uint8_t payload[4] = {0};
409 return _pd.
sendRaw(MSG_REQUEST, payload,
sizeof(payload));
#define SENSORLIB_LOG_W(...)
#define SENSORLIB_LOG_E(...)
bool handleIrq(const RequestParams &req, Event &outEvent, SourceCaps *outCaps=nullptr)
Process one TCPC IRQ status sample.
@ WaitAccept
Request sent; waiting for Accept.
@ Success
Requested contract is ready.
@ WaitPsRdy
Accept received; waiting for PS_RDY.
@ WaitSourceCap
Waiting for Source_Capabilities.
@ Failed
Negotiation failed.
@ Idle
Not initialized or inactive.
AXP517PdNegotiator(AXP517Tcpc &tcpc, AXP517Pd &pd)
Construct a negotiator from the low-level TCPC and PD helpers.
bool selectFixedOffer(const SourceCaps &caps, const RequestParams &req, FixedOffer &outOffer)
Select one fixed PDO offer matching the request.
bool hasIrqPin() const
Check whether a valid IRQ pin is configured.
void reset()
Reset message IDs and return to the initial wait state.
bool negotiate(const RequestParams &req, SourceCaps *outCaps=nullptr, uint32_t timeoutMs=6000)
Run a blocking fixed PDO negotiation.
bool setIrqPin(int irqPin)
Configure the PMIC/TCPC IRQ pin used for PD negotiation.
bool requestFromCaps(const SourceCaps &caps, const RequestParams &req)
Send a Request message selected from parsed source capabilities.
bool service(const RequestParams &req, Event &outEvent, SourceCaps *outCaps=nullptr)
Service pending IRQ-driven PD events.
bool parseSourceCaps(const AXP517Tcpc::RxFifoMsg &rx, SourceCaps &outCaps)
Parse fixed PDOs from a Source_Capabilities RX message.
bool initSink(int irqPin)
Initialize the TCPC sink and configure the PD receive path.
bool isDone() const
Check whether negotiation reached a terminal state.
bool isSuccess() const
Check whether negotiation completed successfully.
Event
Event reported by service() and handleIrq().
@ PsRdy
PS_RDY received; contract is active.
@ TxDiscarded
TCPC discarded TX due to RX activity.
@ TxFailed
TCPC reported TX failure.
@ None
No meaningful state change.
@ HardReset
Hard Reset received.
@ RequestSent
Request message transmitted.
@ Accept
Accept control message received.
@ SourceCapabilities
Source_Capabilities received.
@ Reject
Reject control message received.
@ CcDetached
CC or VBUS detach detected.
@ TxSuccess
TCPC reported TX success.
@ CcChanged
CC state changed while attached.
USB-PD message builder and FIFO helper for AXP517.
void resetMsgId()
Reset the local USB-PD message ID counter to zero.
bool sendRaw(uint8_t msgType, const uint8_t *payload, uint8_t payloadLen)
Send a raw USB-PD data message.
bool setReceiveDetectSop(bool enable)
Enable or disable SOP receive detection.
bool configureHeaderInfo(const HeaderInfoCfg &cfg)
Configure local message-header defaults.
AXP517 Type-C Port Controller helper.
uint8_t digitalRead(uint8_t pin)
Read a platform GPIO pin through the active HAL.
bool clearAlert(uint16_t maskRw1c)
Clear PD_ALERTL/H bits using write-one-to-clear semantics.
bool setSinkMessageHeaderAndRx()
Configure sink message-header defaults and enable SOP RX.
bool clearPmicIrqStatus()
Clear the non-PD PMIC IRQ status registers.
bool init()
Initialize the TCPC as a USB-PD sink.
bool clearTx()
Reset the TX byte count and transmit command register.
void pinMode(uint8_t pin, uint8_t mode)
Configure a platform GPIO pin through the active HAL.
bool clearFaultStatus(uint8_t maskRw1c)
Clear TCPC FAULT_STATUS bits using write-one-to-clear semantics.
bool isAttached()
Check whether either CC pin indicates attachment.
bool readFaultStatus(uint8_t &out)
Read the TCPC FAULT_STATUS register.
void delayMs(uint32_t ms)
Delay using the active platform HAL.
@ AlertTxFailed
Message transmission failed.
@ AlertPowerStatus
POWER_STATUS register changed.
@ AlertTxSuccess
Message transmission completed.
@ AlertRxHardReset
Hard Reset received.
@ AlertRxStatus
RX buffer contains a SOP message.
@ AlertTxDiscarded
Transmission discarded due to RX activity.
@ AlertFault
TCPC fault status changed.
@ AlertVbusDisconnect
VBUS sink disconnect threshold crossed.
@ AlertCcStatus
CC_STATUS register changed.
bool writeReceiveDetect(uint8_t v)
Write the TCPCI RECEIVE_DETECT register.
bool readAlert(uint16_t &out)
Read PD_ALERTL/H.
bool rxReadMessage(RxFifoMsg &out)
Read and decode one TCPC RX FIFO message.
uint32_t millis()
Return the platform millisecond counter.
bool checkVendorId()
Verify the TCPC vendor ID.
bool clearAllAlerts()
Clear all PD alert bits.
bool isVbusPresent()
Check whether TCPC VBUS present status is set.
bool setPolarityFromCc()
Set TCPC polarity from the current CC status.
USB Power Delivery protocol helper definitions.
bool parseFixedSourcePdo(uint32_t pdo, FixedSourcePdo &out)
Parse a fixed source PDO.
void wr_le32(uint8_t *p, uint32_t v)
Write a 32-bit value to a byte buffer in little-endian order.
uint32_t le32(const uint8_t *p)
Read a 32-bit little-endian integer from a byte buffer.
uint32_t buildRdoFixedCurrent(uint8_t objectPos1based, uint16_t opMa, uint16_t maxMa, bool capMismatch=false, bool usbCommCapable=true, bool noUsbSuspend=true)
Build a fixed-current Request Data Object.
One fixed supply PDO offered by the source.
uint16_t mv
Fixed supply voltage in millivolts.
uint32_t rawPdo
Raw 32-bit PDO value.
uint8_t pdoIndex1Based
USB-PD object position, 1 through 7.
uint16_t maMax
Maximum current in milliamps.
Requested sink operating point.
uint8_t pdoIndex1Based
Optional explicit source PDO index, 1 through 7.
uint16_t targetMv
Optional fixed PDO voltage to select.
Parsed Source_Capabilities message.
uint16_t rawHeaderLE
Raw Source_Capabilities header.
uint8_t totalPdoCount
Total PDO count advertised in the message.
FixedOffer fixed[7]
Parsed fixed PDO offers.
uint8_t fixedCount
Number of valid entries in fixed[].
uint16_t headerLE
USB-PD message header in little-endian order.
uint8_t payload[28]
USB-PD payload bytes.
uint8_t payloadLen
Number of valid payload bytes.
Parsed fixed source PDO fields.