66#if EFI_PROD_CODE && defined( HELLEN_BOARD_ID_PIN_1) && !defined(HW_HELLEN_SKIP_BOARD_TYPE)
72 palClearPad(
state->rOutputPinPort,
state->rOutputPinIdx);
74 state->timeChargeNt = nowNt;
76 chibios_rt::CriticalSectionLocker csl;
77 chSemSignalI(&
state->boardId_wake);
90 k3 = iC * (Tc1 - Tc2);
93 auto result = NewtonsMethodSolver::solve(x0, deltaX, 20);
98 criticalError(
"hellen boardID is broken");
107 static const float rOnlyMajorValues[] = {
108 HELLEN_BOARD_ID_MAJOR_RESISTORS
112 static const float rAllValues[] = {
114 HELLEN_BOARD_ID_MAJOR_RESISTORS
116 HELLEN_BOARD_ID_MINOR_RESISTORS
119 size_t rValueSize = testOnlyMajorSeries ? efi::size(rOnlyMajorValues) : efi::size(rAllValues);
122 float minDelta = 1.e6f;
123 for (
size_t i = 0; i < rValueSize; i++) {
125 float delta = std::abs(1 - (R / rAllValues[i]));
126 if (delta < minDelta) {
129#ifdef HELLEN_BOARD_ID_DEBUG
130 efiPrintf(
"* [%d] R = %.0f, delta = %f", i, rAllValues[i], delta);
134 return rAllValues[*rIdx];
138 constexpr float Vcc = 3.3f - 0.1f;
139 constexpr float V01 = Vcc * 0.5f;
141 float log1V01Vcc = log(1.0f - V01 / Vcc);
143 float Rest = -Tc1_us / (
C * log1V01Vcc);
148 constexpr float Cest = HELLEN_BOARD_ID_CAPACITOR;
153 *Rmeasured = rSolver.
solve(Tc1_us, Tc2_us, Rest,
C, 1.0f);
158 constexpr float Rinternal = 22.0f;
165 constexpr float capacitorPrecision = 0.1f;
166 constexpr float Cmin = Cest * (1.0f - capacitorPrecision);
167 constexpr float Cmax = Cest * (1.0f + capacitorPrecision);
170 *newC = cSolver.
solve(Tc1_us, Tc2_us, Cmin, R + Rinternal, 0.01f);
172 *newC = clampF(Cmin, *newC, Cmax);
177template <
size_t NumPins>
179#if EFI_PROD_CODE && defined( HELLEN_BOARD_ID_PIN_1) && !defined(HW_HELLEN_SKIP_BOARD_TYPE)
180 chSemReset(&
state.boardId_wake, 0);
183 const int Tf_us = 50000;
186 for (
size_t k = 0; k < NumPins; k++) {
191 chThdSleepMicroseconds(Tf_us);
196 palSetPadMode(
state.rOutputPinPort,
state.rOutputPinIdx, PAL_MODE_OUTPUT_PUSHPULL);
199 int inputIdx = 1 - i;
203 palSetPadMode(
state.rInputPinPort,
state.rInputPinIdx, PAL_MODE_INPUT);
206 int pinState = palReadPad(
state.rInputPinPort,
state.rInputPinIdx);
209 efiPrintf(
"* Board detection error!");
220 state.timeChargeNt = 0;
222 palSetPad(
state.rOutputPinPort,
state.rOutputPinIdx);
223 chSemWaitTimeout(&
state.boardId_wake, TIME_US2I(Tf_us));
224 efitick_t t2 =
state.timeChargeNt;
231 if (t2 - t1 < US2NT(100)) {
232 efiPrintf(
"* Hellen Board ID circuitry wasn't detected! Aborting!");
238 Tc1_us = NT2USF(Tc1_nt);
244 efitick_t t3 = t2 + Td_nt;
248 pinState = palReadPad(
state.rInputPinPort,
state.rInputPinIdx);
251 state.timeChargeNt = 0;
252 palSetPad(
state.rOutputPinPort,
state.rOutputPinIdx);
255 chSemReset(&
state.boardId_wake, 0);
256 chSemWaitTimeout(&
state.boardId_wake, TIME_US2I(Tf_us));
257 efitick_t t4 =
state.timeChargeNt;
260 Tc2_us = NT2USF(t4 - t3);
262 float Td_us = NT2USF(Td_nt);
263#ifdef HELLEN_BOARD_ID_DEBUG
264 efiPrintf(
"* dTime2-1 = %d", (
int)(t2 - t1));
265 efiPrintf(
"* dTime3-2 = %d", (
int)(t3 - t2));
266 efiPrintf(
"* dTime4-3 = %d", (
int)(t4 - t3));
267 efiPrintf(
"* Tc1 = %f, Tc2 = %f, Td = %f", Tc1_us, Tc2_us, Td_us);
272 efiPrintf(
"* Board detection error! (Td=%f is too small)", Td_us);
277 efiPrintf(
"* Estimates are out of limit! Something went wrong. Aborting!");
286template <
size_t NumPins>
288 const int numTries = 3;
292 for (
int tries = 0; tries < numTries; tries++) {
294 float Tc1i_us = 0, Tc2i_us = 0;
295 if (!measureChargingTimes(i, Tc1i_us, Tc2i_us))
310#if defined( HELLEN_BOARD_ID_PIN_1) && !defined(HW_HELLEN_SKIP_BOARD_TYPE)
311 efiPrintf(
"Starting Hellen Board ID detection...");
315 const int numPins = 2;
316 Gpio rPins[numPins] = { HELLEN_BOARD_ID_PIN_1, HELLEN_BOARD_ID_PIN_2};
319 float C = HELLEN_BOARD_ID_CAPACITOR;
322 float R[numPins] = { 0 };
323 int rIdx[numPins] = { 0 };
331 for (
int i = 0; i < numPins; i++) {
332#ifdef HELLEN_BOARD_ID_DEBUG
333 efiPrintf(
"*** Resistor R%d...", i + 1);
336 float Tc1_us = 0, Tc2_us = 0;
345 if (Rest < 300.0f || Rest > 15000.0f) {
346 efiPrintf(
"* Unrealistic estimated resistor value (%f)! Aborting!", Rest);
351 bool testOnlyMajorSeries = (i == 0);
353 float Rmeasured, newC;
355 R[i] = finder.
calc(Tc1_us, Tc2_us, Rest,
C, testOnlyMajorSeries, &Rmeasured, &newC, &rIdx[i]);
358#ifdef HELLEN_BOARD_ID_DEBUG
359 efiPrintf(
"* R = %f, Rmeasured = %f, Rest = %f, Creal = %f", R[i], Rmeasured, Rest,
C);
364 for (
size_t k = 0; k < numPins; k++) {
370 float elapsed_Ms = t.getElapsedSeconds() * 1000;
373 bool allRValid =
true;
374 for (
size_t i = 0; i < numPins; i++) {
375 allRValid &= R[i] != 0;
380 boardId = HELLEN_GET_BOARD_ID(rIdx[0], rIdx[1]);
385 efiPrintf(
"* RESULT: BoardId = %d, R1 = %.0f, R2 = %.0f (Elapsed time: %.1f ms)", boardId, R[0], R[1], elapsed_Ms);
float findClosestResistor(float R, bool testOnlyMajorSeries, int *rIdx)
float calc(float Tc1_us, float Tc2_us, float Rest, float C, bool testOnlyMajorSeries, float *Rmeasured, float *Cest, int *rIdx)
float calcEstimatedResistance(float Tc1_us, float C)
bool measureChargingTimesAveraged(int i, float &Tc1_us, float &Tc2_us)
HellenBoardIdFinderState state
bool measureChargingTimes(int i, float &Tc1_us, float &Tc2_us)
float solve(float Tc1, float Tc2, float x0, float y, float deltaX)
static void hellenBoardIdInputCallback(void *arg, efitick_t nowNt)
int detectHellenBoardId()
Board-Id detector for Hellen boards.
UNUSED(samplingTimeSeconds)
int getBrainPinIndex(Gpio brainPin)
ioportid_t getBrainPinPort(brain_pin_e brainPin)
state("state", SensorCategory.SENSOR_INPUTS, FieldType.INT8, 1871, 1.0, -1.0, -1.0, "")