mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
Rough handler for capabilities
This commit is contained in:
@@ -90,6 +90,25 @@ bool USBPowerDelivery::isVBUSConnected() {
|
|||||||
uint32_t lastCapabilities[11];
|
uint32_t lastCapabilities[11];
|
||||||
uint32_t *USBPowerDelivery::getLastSeenCapabilities() { return lastCapabilities; }
|
uint32_t *USBPowerDelivery::getLastSeenCapabilities() { return lastCapabilities; }
|
||||||
|
|
||||||
|
static unsigned int sqrtI(unsigned long sqrtArg) {
|
||||||
|
unsigned int answer, x;
|
||||||
|
unsigned long temp;
|
||||||
|
if (sqrtArg == 0)
|
||||||
|
return 0; // undefined result
|
||||||
|
if (sqrtArg == 1)
|
||||||
|
return 1; // identity
|
||||||
|
answer = 0; // integer square root
|
||||||
|
for (x = 0x8000; x > 0; x = x >> 1) { // 16 bit shift
|
||||||
|
answer |= x; // possible bit in root
|
||||||
|
temp = answer * answer; //
|
||||||
|
if (temp == sqrtArg)
|
||||||
|
break; // exact, found it
|
||||||
|
if (temp > sqrtArg)
|
||||||
|
answer ^= x; // too large, reverse bit
|
||||||
|
}
|
||||||
|
return answer; // approximate root
|
||||||
|
}
|
||||||
|
|
||||||
// parseCapabilitiesArray returns true if a valid capability was found
|
// parseCapabilitiesArray returns true if a valid capability was found
|
||||||
// caps is the array of capabilities objects
|
// caps is the array of capabilities objects
|
||||||
// best* are output references
|
// best* are output references
|
||||||
@@ -127,31 +146,49 @@ bool parseCapabilitiesArray(const uint8_t numCaps, uint8_t *bestIndex, uint16_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if ((lastCapabilities[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED && (((lastCapabilities[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS))) {
|
||||||
|
// If this is a PPS slot, calculate the max voltage in the PPS range that can we be used and maintain
|
||||||
|
uint16_t max_voltage = PD_PAV2MV(PD_APDO_PPS_MAX_VOLTAGE_GET(lastCapabilities[i]));
|
||||||
|
// uint16_t min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCapabilities[i]));
|
||||||
|
uint16_t max_current = PD_PAI2CA(PD_APDO_PPS_CURRENT_GET(lastCapabilities[i])); // max current in 10mA units
|
||||||
|
// Using the current and tip resistance, calculate the ideal max voltage
|
||||||
|
// if this is range, then we will work with this voltage
|
||||||
|
// if this is not in range; then max_voltage can be safely selected
|
||||||
|
int ideal_voltage_mv = (tipResistance * max_current);
|
||||||
|
if (ideal_voltage_mv > max_voltage) {
|
||||||
|
ideal_voltage_mv = max_voltage; // constrain to what this PDO offers
|
||||||
|
}
|
||||||
|
if (ideal_voltage_mv > (USB_PD_VMAX * 1000)) {
|
||||||
|
ideal_voltage_mv = (USB_PD_VMAX * 1000); // constrain to model max voltage safe to select
|
||||||
|
}
|
||||||
|
if (ideal_voltage_mv > *bestVoltage) {
|
||||||
|
*bestIndex = i;
|
||||||
|
*bestVoltage = ideal_voltage_mv;
|
||||||
|
*bestCurrent = max_current;
|
||||||
|
*bestIsPPS = true;
|
||||||
|
}
|
||||||
|
} else if ((lastCapabilities[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED && (((lastCapabilities[i] & PD_APDO_TYPE) == PD_APDO_TYPE_AVS))) {
|
||||||
|
*bestIsAVO = true;
|
||||||
|
uint16_t max_voltage = PD_PAV2MV(PD_APDO_AVS_MAX_VOLTAGE_GET(lastCapabilities[i]));
|
||||||
|
uint16_t min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCapabilities[i]));
|
||||||
|
uint8_t max_wattage = PD_APDO_AVS_MAX_POWER_GET(lastCapabilities[i]);
|
||||||
|
|
||||||
|
// W = v^2/tip_resistance => Wattage*tip_resistance == Max_volage^2
|
||||||
|
auto ideal_max_voltage = sqrtI((max_wattage * tipResistance) / 10);
|
||||||
|
MSG((char *)"AVS min %d max %d wattage %d tipRes %d sqrt %d\r\n", min_voltage, max_voltage, max_wattage, tipResistance, ideal_max_voltage);
|
||||||
|
if (ideal_max_voltage > (USB_PD_VMAX * 1000)) {
|
||||||
|
ideal_max_voltage = (USB_PD_VMAX * 1000); // constrain to model max voltage safe to select
|
||||||
|
}
|
||||||
|
auto operating_current = (ideal_max_voltage / tipResistance) / 100; // Current in mA
|
||||||
|
|
||||||
|
MSG((char *)"AVS min %d max %d wattage %d tipRes %d sqrt %d -> %d\r\n", min_voltage, max_voltage, max_wattage, tipResistance, ideal_max_voltage, operating_current);
|
||||||
|
if (ideal_max_voltage > *bestVoltage) {
|
||||||
|
*bestIndex = i;
|
||||||
|
*bestVoltage = ideal_max_voltage;
|
||||||
|
*bestCurrent = operating_current;
|
||||||
|
*bestIsPPS = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// else if ((lastCapabilities[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED
|
|
||||||
// && (((lastCapabilities[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) || ((lastCapabilities[i] & PD_APDO_TYPE) == PD_APDO_TYPE_AVS))) {
|
|
||||||
// // If this is a PPS slot, calculate the max voltage in the PPS range that can we be used and maintain
|
|
||||||
// uint16_t max_voltage = PD_PAV2MV(PD_APDO_PPS_MAX_VOLTAGE_GET(lastCapabilities[i]));
|
|
||||||
// // uint16_t min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCapabilities[i]));
|
|
||||||
// uint16_t max_current = PD_PAI2CA(PD_APDO_PPS_CURRENT_GET(lastCapabilities[i])); // max current in 10mA units
|
|
||||||
// // Using the current and tip resistance, calculate the ideal max voltage
|
|
||||||
// // if this is range, then we will work with this voltage
|
|
||||||
// // if this is not in range; then max_voltage can be safely selected
|
|
||||||
// int ideal_voltage_mv = (getTipResitanceX10() * max_current);
|
|
||||||
// if (ideal_voltage_mv > max_voltage) {
|
|
||||||
// ideal_voltage_mv = max_voltage; // constrain to what this PDO offers
|
|
||||||
// }
|
|
||||||
// if (ideal_voltage_mv > (USB_PD_VMAX * 1000)) {
|
|
||||||
// ideal_voltage_mv = (USB_PD_VMAX * 1000); // constrain to model max voltage safe to select
|
|
||||||
// }
|
|
||||||
// if (ideal_voltage_mv > bestVoltage) {
|
|
||||||
// bestIndex = i;
|
|
||||||
// bestVoltage = ideal_voltage_mv;
|
|
||||||
// bestCurrent = max_current;
|
|
||||||
// bestIsPPS = (lastCapabilities[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS;
|
|
||||||
// bestIsAVO = (lastCapabilities[i] & PD_APDO_TYPE) == PD_APDO_TYPE_AVS;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that the best index is known, set the current values
|
// Now that the best index is known, set the current values
|
||||||
@@ -165,18 +202,20 @@ bool EPREvaluateCapabilityFunc(const epr_pd_msg *capabilities, pd_msg *request)
|
|||||||
memcpy(lastCapabilities, capabilities->obj, sizeof(lastCapabilities));
|
memcpy(lastCapabilities, capabilities->obj, sizeof(lastCapabilities));
|
||||||
// PDO slots 1-7 shall be the standard PDO's
|
// PDO slots 1-7 shall be the standard PDO's
|
||||||
// PDO slots 8-11 shall be the >20V slots
|
// PDO slots 8-11 shall be the >20V slots
|
||||||
uint8_t numobj = PD_NUMOBJ_GET(capabilities);
|
uint8_t numobj = 11;
|
||||||
uint8_t bestIndex = 0xFF;
|
uint8_t bestIndex = 0xFF;
|
||||||
uint16_t bestIndexVoltage = 0;
|
uint16_t bestIndexVoltage = 0;
|
||||||
uint16_t bestIndexCurrent = 0;
|
uint16_t bestIndexCurrent = 0;
|
||||||
bool bestIsPPS = false;
|
bool bestIsPPS = false;
|
||||||
bool bestIsAVO = false;
|
bool bestIsAVO = false;
|
||||||
|
MSG((char *)"EPR Eval - %d\r\n", numobj);
|
||||||
if (parseCapabilitiesArray(numobj, &bestIndex, &bestIndexVoltage, &bestIndexCurrent, &bestIsPPS, &bestIsAVO)) {
|
if (parseCapabilitiesArray(numobj, &bestIndex, &bestIndexVoltage, &bestIndexCurrent, &bestIsPPS, &bestIsAVO)) {
|
||||||
/* We got what we wanted, so build a request for that */
|
/* We got what we wanted, so build a request for that */
|
||||||
request->hdr = PD_MSGTYPE_EPR_REQUEST | PD_NUMOBJ(2);
|
request->hdr = PD_MSGTYPE_EPR_REQUEST | PD_NUMOBJ(2);
|
||||||
request->obj[1] = lastCapabilities[bestIndex]; // Copy PDO into slot 2
|
request->obj[1] = lastCapabilities[bestIndex]; // Copy PDO into slot 2
|
||||||
if (bestIsPPS | bestIsAVO) {
|
if (bestIsAVO) {
|
||||||
|
request->obj[0] = PD_RDO_PROG_CURRENT_SET(PD_CA2PAI(bestIndexCurrent)) | PD_RDO_PROG_VOLTAGE_SET(PD_MV2APS(bestIndexVoltage)) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(bestIndex + 1);
|
||||||
|
} else if (bestIsPPS) {
|
||||||
request->obj[0] = PD_RDO_PROG_CURRENT_SET(PD_CA2PAI(bestIndexCurrent)) | PD_RDO_PROG_VOLTAGE_SET(PD_MV2PRV(bestIndexVoltage)) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(bestIndex + 1);
|
request->obj[0] = PD_RDO_PROG_CURRENT_SET(PD_CA2PAI(bestIndexCurrent)) | PD_RDO_PROG_VOLTAGE_SET(PD_MV2PRV(bestIndexVoltage)) | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(bestIndex + 1);
|
||||||
} else {
|
} else {
|
||||||
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);
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user