diff --git a/source/Core/BSP/BSP_PD.h b/source/Core/BSP/BSP_PD.h index ef65a52a..a0dde7c2 100644 --- a/source/Core/BSP/BSP_PD.h +++ b/source/Core/BSP/BSP_PD.h @@ -8,9 +8,5 @@ #ifndef USER_BSP_PD_H_ #define USER_BSP_PD_H_ #include "BSP.h" -/* - * An array of all of the desired voltages & minimum currents in preferred order - */ -extern const uint16_t USB_PD_Desired_Levels[]; -extern const uint8_t USB_PD_Desired_Levels_Len; + #endif /* USER_BSP_PD_H_ */ diff --git a/source/Core/BSP/Miniware/BSP_PD.c b/source/Core/BSP/Miniware/BSP_PD.c index 0083caeb..f2612726 100644 --- a/source/Core/BSP/Miniware/BSP_PD.c +++ b/source/Core/BSP/Miniware/BSP_PD.c @@ -8,15 +8,5 @@ #include "BSP_PD.h" #include "Model_Config.h" #ifdef POW_PD -/* - * An array of all of the desired voltages & minimum currents in preferred order - */ -const uint16_t USB_PD_Desired_Levels[] = { - // mV desired input, mA minimum required current - 12000, 2400, // 12V @ 2.4A - 9000, 2000, // 9V @ 2A - 5000, 100, // 5V @ whatever -}; -const uint8_t USB_PD_Desired_Levels_Len = 3; #endif diff --git a/source/Core/BSP/Pine64/BSP_PD.c b/source/Core/BSP/Pine64/BSP_PD.c index 8608c814..f2612726 100644 --- a/source/Core/BSP/Pine64/BSP_PD.c +++ b/source/Core/BSP/Pine64/BSP_PD.c @@ -8,19 +8,5 @@ #include "BSP_PD.h" #include "Model_Config.h" #ifdef POW_PD -/* - * An array of all of the desired voltages & minimum currents in preferred order - */ -const uint16_t USB_PD_Desired_Levels[] = { - // mV desired input, mA minimum required current - // Tip is ~ 7.5 ohms - 20000, 2666, // 20V, 2.6A - 18000, 2400, // 18V, 2.4A - 15000, 2000, // 15V 2A - 12000, 1600, // 12V @ 1.6A - 9000, 1200, // 9V @ 1.2A - 5000, 100, // 5V @ whatever -}; -const uint8_t USB_PD_Desired_Levels_Len = 6; #endif diff --git a/source/Core/Drivers/FUSB302/policy_engine_user.cpp b/source/Core/Drivers/FUSB302/policy_engine_user.cpp index 0241436b..06a6c387 100644 --- a/source/Core/Drivers/FUSB302/policy_engine_user.cpp +++ b/source/Core/Drivers/FUSB302/policy_engine_user.cpp @@ -5,8 +5,10 @@ * Author: Ralim */ #include "BSP_PD.h" +#include "configuration.h" #include "pd.h" #include "policy_engine.h" + /* The current draw when the output is disabled */ #define DPM_MIN_CURRENT PD_MA2PDI(50) /* @@ -54,52 +56,65 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability(const union pd_msg *capabilities /* Make sure we have configuration */ /* Look at the PDOs to see if one matches our desires */ // Look against USB_PD_Desired_Levels to select in order of preference - for (uint8_t desiredLevel = 0; desiredLevel < USB_PD_Desired_Levels_Len; desiredLevel++) { - for (uint8_t i = 0; i < numobj; i++) { - /* If we have a fixed PDO, its V equals our desired V, and its I is - * at least our desired I */ - if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { - // This is a fixed PDO entry - int voltage = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i])); - int current = PD_PDO_SRC_FIXED_CURRENT_GET(capabilities->obj[i]); - uint16_t desiredVoltage = USB_PD_Desired_Levels[(desiredLevel * 2) + 0]; - uint16_t desiredminCurrent = USB_PD_Desired_Levels[(desiredLevel * 2) + 1]; - // As pd stores current in 10mA increments, divide by 10 - desiredminCurrent /= 10; - if (voltage == desiredVoltage) { - if (current >= desiredminCurrent) { - /* We got what we wanted, so build a request for that */ - request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); + uint8_t bestIndex = 0xFF; + int bestIndexVoltage = 0; + int bestIndexCurrent = 0; + for (uint8_t i = 0; i < numobj; i++) { + /* If we have a fixed PDO, its V equals our desired V, and its I is + * at least our desired I */ + if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) { + // This is a fixed PDO entry + // Evaluate if it can produve sufficient current based on the tipResistance (ohms*10) + // V=I*R -> V/I => minimum resistance, if our tip resistance is >= this then we can use this supply - /* GiveBack disabled */ - request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(current) | PD_RDO_FV_CURRENT_SET(current) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1); - // We support usb comms (ish) - request->obj[0] |= PD_RDO_USB_COMMS; - - /* Update requested voltage */ - _requested_voltage = voltage; - - return true; - } + int voltage_mv = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(capabilities->obj[i])); // voltage in mV units + int current_a_x100 = PD_PDO_SRC_FIXED_CURRENT_GET(capabilities->obj[i]); // current in 10mA units + int min_resistance_ohmsx10 = voltage_mv / current_a_x100; + if (min_resistance_ohmsx10 <= tipResistance) { + // This is a valid power source we can select as + if (bestIndex == 0xFF) { + // This is the first valid source, so select to be safe + bestIndex = i; + bestIndexVoltage = voltage_mv; + bestIndexCurrent = current_a_x100; + } else if (voltage_mv > bestIndexVoltage) { + // Higher voltage and valid, select this instead + bestIndex = i; + bestIndexVoltage = voltage_mv; + bestIndexCurrent = current_a_x100; } } } } + if (bestIndex != 0xFF) { + /* We got what we wanted, so build a request for that */ + request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); - /* Nothing matched (or no configuration), so get 5 V at low current */ - request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); - request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(1); - /* If the output is enabled and we got here, it must be a capability - * mismatch. */ - if (pdNegotiationComplete) { - request->obj[0] |= PD_RDO_CAP_MISMATCH; + /* GiveBack disabled */ + request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(bestIndexCurrent) | PD_RDO_FV_CURRENT_SET(bestIndexCurrent) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(bestIndex + 1); + // We support usb comms (ish) + request->obj[0] |= PD_RDO_USB_COMMS; + + /* Update requested voltage */ + _requested_voltage = bestIndexVoltage; + + return true; + } else { + /* Nothing matched (or no configuration), so get 5 V at low current */ + request->hdr = hdr_template | PD_MSGTYPE_REQUEST | PD_NUMOBJ(1); + request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_FV_CURRENT_SET(DPM_MIN_CURRENT) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(1); + /* If the output is enabled and we got here, it must be a capability + * mismatch. */ + if (pdNegotiationComplete) { + request->obj[0] |= PD_RDO_CAP_MISMATCH; + } + request->obj[0] |= PD_RDO_USB_COMMS; + + /* Update requested voltage */ + _requested_voltage = 5000; + + return false; } - request->obj[0] |= PD_RDO_USB_COMMS; - - /* Update requested voltage */ - _requested_voltage = 5000; - - return false; } void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) { @@ -112,8 +127,12 @@ void PolicyEngine::pdbs_dpm_get_sink_capability(union pd_msg *cap) { cap->obj[numobj++] = PD_PDO_TYPE_FIXED | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_MV2PDV(5000)) | PD_PDO_SNK_FIXED_CURRENT_SET(DPM_MIN_CURRENT); /* Get the current we want */ - uint16_t current = USB_PD_Desired_Levels[1] / 10; // In centi-amps - uint16_t voltage = USB_PD_Desired_Levels[0]; // in mv + uint16_t voltage = USB_PD_VMAX * 1000; // in mv + if (_requested_voltage != 5000) { + voltage = _requested_voltage; + } + uint16_t current = (voltage) / tipResistance; // In centi-amps + /* Add a PDO for the desired power. */ cap->obj[numobj++] = PD_PDO_TYPE_FIXED | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_MV2PDV(voltage)) | PD_PDO_SNK_FIXED_CURRENT_SET(current); diff --git a/source/Core/Drivers/FUSB302/protocol_tx.cpp b/source/Core/Drivers/FUSB302/protocol_tx.cpp index fadc68af..d526151b 100644 --- a/source/Core/Drivers/FUSB302/protocol_tx.cpp +++ b/source/Core/Drivers/FUSB302/protocol_tx.cpp @@ -104,17 +104,15 @@ ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_mess temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT; /* PD 3.0 collision avoidance */ - // if (PolicyEngine::isPD3_0()) { - // /* If we're starting an AMS, wait for permission to transmit */ - // evt = waitForEvent((uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS, - // 0); - // if ((uint32_t) evt - // & (uint32_t) Notifications::PDB_EVT_PRLTX_START_AMS) { - // while (fusb_get_typec_current() != fusb_sink_tx_ok) { - // osDelay(1); - // } - // } - // } + if (PolicyEngine::isPD3_0()) { + /* If we're starting an AMS, wait for permission to transmit */ + ProtocolTransmit::Notifications evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PRLTX_START_AMS, 0); + if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_START_AMS) { + while (fusb_get_typec_current() != fusb_sink_tx_ok) { + osDelay(1); + } + } + } messageSending = true; /* Send the message to the PHY */ fusb_send_message(&temp_msg);