/* * QC3.c * * Created on: 29 May 2020 * Author: Ralim */ // Quick charge 3.0 supporting functions #include "QC3.h" #include "BSP.h" #include "cmsis_os.h" #include "stdint.h" void QC_Seek9V() { QC_DNegZero_Six(); QC_DPlusThree_Three(); } void QC_Seek12V() { QC_DNegZero_Six(); QC_DPlusZero_Six(); } void QC_Seek20V() { QC_DNegThree_Three(); QC_DPlusThree_Three(); } void QC_SeekContMode() { QC_DNegThree_Three(); QC_DPlusZero_Six(); } void QC_SeekContPlus() { QC_SeekContMode(); osDelay(30); QC_Seek20V(); osDelay(10); QC_SeekContMode(); } void QC_SeekContNeg() { QC_SeekContMode(); osDelay(30); QC_Seek12V(); osDelay(10); QC_SeekContMode(); } uint8_t QCMode = 0; uint8_t QCTries = 0; void seekQC(int16_t Vx10, uint16_t divisor) { if (QCMode == 0) startQC(divisor); if (Vx10 < 45) return; if (xTaskGetTickCount() < 1000) return; if (Vx10 > 130) Vx10 = 130; // Cap max value at 13V // Seek the QC to the Voltage given if this adapter supports continuous mode // try and step towards the wanted value // 1. Measure current voltage int16_t vStart = getInputVoltageX10(divisor, 1); int difference = Vx10 - vStart; // 2. calculate ideal steps (0.2V changes) int steps = difference / 2; if (QCMode == 3) { if (steps > -2 && steps < 2) return; // dont bother with small steps while (steps < 0) { QC_SeekContNeg(); osDelay(30); steps++; } while (steps > 0) { QC_SeekContPlus(); osDelay(30); steps--; } osDelay(100); } #ifdef ENABLE_QC2 // Re-measure /* Disabled due to nothing to test and code space of around 1k*/ steps = vStart - getInputVoltageX10(divisor, 1); if (steps < 0) steps = -steps; if (steps > 4) { // No continuous mode, so QC2 QCMode = 2; // Goto nearest if (Vx10 > 110) { // request 12V // D- = 0.6V, D+ = 0.6V // Clamp PB3 QC_Seek12V(); } else { // request 9V QC_Seek9V(); } } #endif } // Must be called after FreeRToS Starts void startQC(uint16_t divisor) { // Pre check that the input could be >5V already, and if so, dont both // negotiating as someone is feeding in hv uint16_t vin = getInputVoltageX10(divisor, 1); if (vin > 100) { QCMode = 1; // Already at 12V, user has probably over-ridden this return; } if (QCTries > 10) { return; } QC_Init_GPIO(); // Tries to negotiate QC for 9V // This is a multiple step process. // 1. Set around 0.6V on D+ for 1.25 Seconds or so // 2. After this It should un-short D+->D- and instead add a 20k pulldown on // D- QC_DPlusZero_Six(); // Delay 1.25 seconds uint8_t enteredQC = 0; for (uint16_t i = 0; i < 200 && enteredQC == 0; i++) { osDelay(10); // 10mS pause if (i > 130) { if (QC_DM_PulledDown()) { enteredQC = 1; } if (i == 140) { // For some marginal QC chargers, we try adding a pulldown QC_DM_PullDown(); } } } QC_DM_No_PullDown(); if (enteredQC) { // We have a QC capable charger QC_Seek9V(); QC_Post_Probe_En(); QC_Seek9V(); // Wait for frontend ADC to stabilise QCMode = 4; for (uint8_t i = 0; i < 10; i++) { if (getInputVoltageX10(divisor, 1) > 80) { // yay we have at least QC2.0 or QC3.0 QCMode = 3; // We have at least QC2, pray for 3 return; } osDelay(100); // 100mS } QCMode = 0; QCTries++; } else { // no QC QCMode = 0; } }