diff --git a/firmware/config/boards/hellen/alphax-2chan/board.mk b/firmware/config/boards/hellen/alphax-2chan/board.mk index b746424f63..9bea3e0a98 100644 --- a/firmware/config/boards/hellen/alphax-2chan/board.mk +++ b/firmware/config/boards/hellen/alphax-2chan/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/alphax-2chan/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/alphax-2chan/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/alphax-2chan # Set this if you want a default engine type other than normal alphax-2chan @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - DDEFS += -DTS_NO_SECONDARY # Add them all together @@ -34,6 +28,5 @@ DDEFS += -DEFI_LOGIC_ANALYZER=FALSE # Enable serial pins on expansion header DDEFS += -DEFI_CONSOLE_TX_BRAIN_PIN=GPIOD_6 -DEFI_CONSOLE_RX_BRAIN_PIN=GPIOD_5 -DTS_PRIMARY_PORT=UARTD2 -DSTM32_UART_USE_USART2=1 -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen-common.mk b/firmware/config/boards/hellen/hellen-common.mk new file mode 100644 index 0000000000..9a1ca7c57d --- /dev/null +++ b/firmware/config/boards/hellen/hellen-common.mk @@ -0,0 +1,13 @@ +# Combine the related files for a specific platform and MCU. + +# Target ECU board design +BOARDCPPSRC += $(BOARDS_DIR)/hellen/hellen_common.cpp \ + $(BOARDS_DIR)/hellen/hellen_board_id.cpp + +DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT +DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT +DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT +DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT + +# We are running on Hellen-One hardware! +DDEFS += -DHW_HELLEN=1 diff --git a/firmware/config/boards/hellen/hellen-nb1/board.mk b/firmware/config/boards/hellen/hellen-nb1/board.mk index 451d862914..585c3e78fb 100644 --- a/firmware/config/boards/hellen/hellen-nb1/board.mk +++ b/firmware/config/boards/hellen/hellen-nb1/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen-nb1/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen-nb1/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen-nb1 # Set this if you want a default engine type other than normal hellen-nb1 @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - DDEFS += -DTS_NO_SECONDARY # Add them all together @@ -34,6 +28,4 @@ DDEFS += -DEFI_LOGIC_ANALYZER=FALSE # Enable serial pins on expansion header DDEFS += -DEFI_CONSOLE_TX_BRAIN_PIN=GPIOD_6 -DEFI_CONSOLE_RX_BRAIN_PIN=GPIOD_5 -DTS_PRIMARY_PORT=UARTD2 -DSTM32_UART_USE_USART2=1 -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 - +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen121nissan/board.mk b/firmware/config/boards/hellen/hellen121nissan/board.mk index e39b098cb5..839cced72e 100644 --- a/firmware/config/boards/hellen/hellen121nissan/board.mk +++ b/firmware/config/boards/hellen/hellen121nissan/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen121nissan/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen121nissan/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen121nissan # Set this if you want a default engine type other than normal hellen121nissan @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY=1 -DTS_NO_SECONDARY=1 @@ -32,5 +26,4 @@ DDEFS += -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE # todo: is it broken? DDEFS += -DEFI_LOGIC_ANALYZER=FALSE -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen121vag/board.mk b/firmware/config/boards/hellen/hellen121vag/board.mk index 5f0438d62e..4cf02ac1a2 100644 --- a/firmware/config/boards/hellen/hellen121vag/board.mk +++ b/firmware/config/boards/hellen/hellen121vag/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen121vag/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen121vag/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen121vag # Set this if you want a default engine type other than normal hellen121vag @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY=1 -DTS_NO_SECONDARY=1 @@ -32,6 +26,5 @@ DDEFS += -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE # todo: is it broken? DDEFS += -DEFI_LOGIC_ANALYZER=FALSE -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen128/board.mk b/firmware/config/boards/hellen/hellen128/board.mk index 00a304fd13..7710b05915 100644 --- a/firmware/config/boards/hellen/hellen128/board.mk +++ b/firmware/config/boards/hellen/hellen128/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen128/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen128/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen128 @@ -18,11 +17,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY=1 -DTS_NO_SECONDARY=1 @@ -33,6 +27,5 @@ DDEFS += -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE # todo: is it broken? DDEFS += -DEFI_LOGIC_ANALYZER=FALSE -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen154hyundai/board.mk b/firmware/config/boards/hellen/hellen154hyundai/board.mk index 50dce15d89..be95a9ffae 100644 --- a/firmware/config/boards/hellen/hellen154hyundai/board.mk +++ b/firmware/config/boards/hellen/hellen154hyundai/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen154hyundai/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen154hyundai/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen154hyundai # Set this if you want a default engine type other than normal hellen121nissan @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY=1 -DTS_NO_SECONDARY=1 @@ -32,6 +26,5 @@ DDEFS += -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE # todo: is it broken? DDEFS += -DEFI_LOGIC_ANALYZER=FALSE -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen64_miataNA6_94/board.mk b/firmware/config/boards/hellen/hellen64_miataNA6_94/board.mk index b21678f38d..c0b7e6bd02 100644 --- a/firmware/config/boards/hellen/hellen64_miataNA6_94/board.mk +++ b/firmware/config/boards/hellen/hellen64_miataNA6_94/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen64_miataNA6_94/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen64_miataNA6_94/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen64_miataNA6_94 # Set this if you want a default engine type other than normal hellen64_miataNA6_94 @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY=1 -DTS_NO_SECONDARY=1 @@ -32,5 +26,4 @@ DDEFS += -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE # todo: is it broken? DDEFS += -DEFI_LOGIC_ANALYZER=FALSE -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen72/board.mk b/firmware/config/boards/hellen/hellen72/board.mk index b5a120f55a..5c8b5418a2 100644 --- a/firmware/config/boards/hellen/hellen72/board.mk +++ b/firmware/config/boards/hellen/hellen72/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen72/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen72/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen72 @@ -18,11 +17,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY=1 -DTS_NO_SECONDARY=1 @@ -33,5 +27,4 @@ DDEFS += -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE # todo: is it broken? DDEFS += -DEFI_LOGIC_ANALYZER=FALSE -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen81/board.mk b/firmware/config/boards/hellen/hellen81/board.mk index b996ca26a3..e6174a57bd 100644 --- a/firmware/config/boards/hellen/hellen81/board.mk +++ b/firmware/config/boards/hellen/hellen81/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen81/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen81/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen81 # Set this if you want a default engine type other than normal Hellen81 @@ -20,11 +19,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY -DTS_NO_SECONDARY DDEFS += -DEFI_CAN_SERIAL=TRUE @@ -48,5 +42,4 @@ TRIGGER_USE_ADC = yes DDEFS += -DEFI_OVERRIDE_FAST_ADC_FOR_STM32H7=TRUE -DADC_FAST_DEVICE=ADCD1 -DEFI_USE_ONLY_FAST_ADC=TRUE -DEFI_FASTER_UNIFORM_ADC=TRUE -DADC_MAX_CHANNELS_COUNT=16 -DADC_BUF_DEPTH_FAST=1 -DADC_BUF_NUM_AVG=1 #DDEFS += -DADC_SLOW_DEVICE=ADCD1 -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen88bmw/board.mk b/firmware/config/boards/hellen/hellen88bmw/board.mk index 5f3ec6c091..fe2f6a0001 100644 --- a/firmware/config/boards/hellen/hellen88bmw/board.mk +++ b/firmware/config/boards/hellen/hellen88bmw/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen88bmw/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen88bmw/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen88bmw # Set this if you want a default engine type other than normal hellen88bmw @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - # Disable serial ports on this board as UART3 causes a DMA conflict with the SD card DDEFS += -DTS_NO_PRIMARY=1 -DTS_NO_SECONDARY=1 @@ -32,5 +26,4 @@ DDEFS += -DEFI_ICU_INPUTS=FALSE -DHAL_TRIGGER_USE_PAL=TRUE # todo: is it broken? DDEFS += -DEFI_LOGIC_ANALYZER=FALSE -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellenNA8_96/board.mk b/firmware/config/boards/hellen/hellenNA8_96/board.mk index e1e9de5650..47156f72db 100644 --- a/firmware/config/boards/hellen/hellenNA8_96/board.mk +++ b/firmware/config/boards/hellen/hellenNA8_96/board.mk @@ -1,8 +1,7 @@ # Combine the related files for a specific platform and MCU. # Target ECU board design -BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen-nb1/board_configuration.cpp \ - $(BOARDS_DIR)/hellen/hellen_common.cpp +BOARDCPPSRC = $(BOARDS_DIR)/hellen/hellen-nb1/board_configuration.cpp BOARDINC = $(BOARDS_DIR)/hellen/hellen-nb1 # Set this if you want a default engine type other than normal hellen-nb1 @@ -17,11 +16,6 @@ endif DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE -DDEFS += -DLED_ERROR_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_RUNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_WARNING_BRAIN_PIN_MODE=INVERTED_OUTPUT -DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT - DDEFS += -DTS_NO_SECONDARY # Add them all together @@ -34,6 +28,5 @@ DDEFS += -DEFI_LOGIC_ANALYZER=FALSE # Enable serial pins on expansion header DDEFS += -DEFI_CONSOLE_TX_BRAIN_PIN=GPIOD_6 -DEFI_CONSOLE_RX_BRAIN_PIN=GPIOD_5 -DTS_PRIMARY_PORT=UARTD2 -DSTM32_UART_USE_USART2=1 -# We are running on Hellen-One hardware! -DDEFS += -DHW_HELLEN=1 +include $(BOARDS_DIR)/hellen/hellen-common.mk diff --git a/firmware/config/boards/hellen/hellen_board_id.cpp b/firmware/config/boards/hellen/hellen_board_id.cpp new file mode 100644 index 0000000000..482dfe658b --- /dev/null +++ b/firmware/config/boards/hellen/hellen_board_id.cpp @@ -0,0 +1,382 @@ +/** + * @file boards/hellen/hellen_board_id.cpp + * @brief Board-Id detector for Hellen boards + * + * @author andreika + * @author Andrey Belomutskiy, (c) 2012-2022 + * + * The main idea is to measure the capacitor charge/discharge time + * through a series resistors using standard digital I/O pins. + * One pin is used to provide a Vcc(3.3) or Vdd(0) voltage to the capacitor + * through a resistor, and another pin is used as a digital input. Then vice versa. + * + * The algo: + * 1) Completely discharge the capacitor (all pins are low) + * 2) Charge the capacitor until the voltage crosses the 0->1 voltage threshold (Vt) and measure the charging time #1 (Tc1). + * 3) Immediately discharge the capacitor to some unknown low voltage (Vl) - it should be well below the Vt threshold, + * using the same period of time used for charging as the discharge period (Td = Tc1). + * 4) Immediately charge the capacitor again and measure the time crossing the same 0->1 voltage threshold again (Tc2). + * 5) Repeat the procedure several times to get more precise timings. + * 6) Do some math and find the R and C values. + * 7) Board_Id = the unique combination of indices of the "measured" R1 and R2. + * + * The math proof: + * - Charging formula #1: + * Vt = Vññ * (1 - exp(-Tc1 / RC)) + * - Discharging formula: + * Vl = Vt * exp(-Td / RC) + * - Charging formula #2: + * Vl = Vññ * (1 - exp(-Tl / (RC))) + * - Where Tl is a charging time from 0 to Vl: + * Tl = Tc1 - Tc2 + * - Solve the equations: + * Vl = Vññ * (1 - exp(-Tl / RC)) = Vt * exp(-Td / RC) + * Vññ * (1 - exp(-Tl / RC)) = Vññ * (1 - exp(-Tc1 / RC)) * exp(-Td / RC) + * (1 - exp(-Tl / RC)) = (1 - exp(-Tc1 / RC)) * exp(-Td / RC) + * - Simplify the equation: + * X = exp(-1/(RC)) + * (1 - X^Tc1) * X^Td + X^Tl - 1 = 0 + * + * X^Td - X^(Tc1+Td) + X^(Tc2-Tc1) - 1 = 0 + * + * Td, Tc1 and Tc2 are known. + * - Solve the power function for X and get the desired R or C. + * + * We use Newton's method (a fast-converging numerical solver when the 1st derivative is known) + * with estimated initial values. + */ + +#include "pch.h" +#include "hellen_meta.h" +#include "digital_input_exti.h" + +#include "hellen_board_id.h" + +/* We use known standard E24 series resistor values (1%) to find the closest match. + The 16 major values should have a guarateed spacing of 15% in a row (1% R tolerance + 10% C tolerance) + These should match the values in the gen_board_id script! +*/ +#include "hellen_board_id_resistors.h" + +//#define HELLEN_BOARD_ID_DEBUG + +#if EFI_PROD_CODE +#if STM32_GPT_USE_TIM6 +#define HELLEN_BOARD_ID_GPTDEVICE GPTD6 +#else +#error "STM32_GPT_USE_TIM6 is required for Hellen Board-ID detector!" +#endif /* STM32_GPT_USE_TIM6 */ + +static void hellenBoardIdInputCallback(void *arg, efitick_t nowNt) { + UNUSED(arg); + chibios_rt::CriticalSectionLocker csl; + + HellenBoardIdFinderState *state = (HellenBoardIdFinderState *)arg; + + // Now start discharging immediately! This should be the first command in the interrupt handler. + palClearPad(state->rOutputPinPort, state->rOutputPinIdx); + + state->timeChargeNt = nowNt; + + chSemSignalI(&state->boardId_wake); // no need to call chSchRescheduleS() because we're inside the ISR +} + +#endif /* EFI_PROD_CODE */ + +// Newton's numerical method (x is R and y is C, or vice-versa) +float HellenBoardIdSolver::solve(float Tc1, float Tc2, float x0, float y, float deltaX) { + // the discharge time equals to the charge time + float Td = Tc1; + + float iC = -1.0f / y; + k1 = iC * Td; + k2 = iC * (Tc1 + Td); + k3 = iC * (Tc1 - Tc2); + + // the same method works for R (if C is known) or C (if R is known) + float Xcur, Xnext; + Xnext = x0; + + do { + Xcur = Xnext; + Xnext = Xcur - fx(Xcur) / dfx(Xcur); + +#ifdef HELLEN_BOARD_ID_DEBUG + efiPrintf ("* %f", Xnext); +#endif /* HELLEN_BOARD_ID_DEBUG */ + } while (absF(Xnext - Xcur) > deltaX); + + return Xnext; +} + +float HellenBoardIdFinderBase::findClosestResistor(float R, bool testOnlyMajorSeries, int *rIdx) { + // the first "major" resistor uses less values (with more spacing between them) so that even less precise method cannot fail. + static const float rOnlyMajorValues[] = { + HELLEN_BOARD_ID_MAJOR_RESISTORS + }; + // the minor resistor is always measured after the major one, when the exact capacitance is already knows, + // so we can use more values and detect them with better precision. + static const float rAllValues[] = { + // these are equal to the major values and should be used first + HELLEN_BOARD_ID_MAJOR_RESISTORS + // these are extended series if 256 board IDs aren't enough (16*16). + HELLEN_BOARD_ID_MINOR_RESISTORS + }; + + size_t rValueSize = testOnlyMajorSeries ? efi::size(rOnlyMajorValues) : efi::size(rAllValues); + + *rIdx = -1; + float minDelta = 1.e6f; + for (size_t i = 0; i < rValueSize; i++) { + float delta = absF(R - rAllValues[i]); + if (delta < minDelta) { + minDelta = delta; + *rIdx = i; +#ifdef HELLEN_BOARD_ID_DEBUG + efiPrintf("* [%d] R = %.0f, delta = %f", i, rAllValues[i], delta); +#endif /* HELLEN_BOARD_ID_DEBUG */ + } + } + return rAllValues[*rIdx]; +} + +float HellenBoardIdFinderBase::calcEstimatedResistance(float Tc1_us, float C) { + constexpr float Vcc = 3.3f - 0.1f; // STM32 digital I/O voltage (adjusted for minor voltage drop) + constexpr float V01 = Vcc * 0.5f; // let it be 1.6 volts (closer to the datasheet value), the exact value doesn't matter + // macos compiler doesn't like log() in constexpr + float log1V01Vcc = log(1.0f - V01 / Vcc); + // this is only an estimated value, we cannot use it for Board-ID detection! + float Rest = -Tc1_us / (C * log1V01Vcc); + return Rest; +} + +float HellenBoardIdFinderBase::calc(float Tc1_us, float Tc2_us, float Rest, float C, bool testOnlyMajorSeries, float *Rmeasured, float *newC, int *rIdx) { + constexpr float Cest = HELLEN_BOARD_ID_CAPACITOR; + // Now calculate the resistance value + HellenBoardIdSolver rSolver; + + // solve the equation for R (1 Ohm precision is more than enough) + *Rmeasured = rSolver.solve(Tc1_us, Tc2_us, Rest, C, 1.0f); + + // add 30 Ohms for pin's internal resistance + // (according to the STM32 datasheets, the voltage drop on an output pin can be up to 0.4V for 8 mA current) + constexpr float Rinternal = 30.0f; + float R = findClosestResistor(*Rmeasured - Rinternal, testOnlyMajorSeries, rIdx); + + // Find the 'real' capacitance value and use it for the next resistor iteration (gives more precision) + HellenBoardIdSolver cSolver; + + // We expect the capacitance to be +-10% + constexpr float capacitorPrecision = 0.1f; + constexpr float Cmin = Cest * (1.0f - capacitorPrecision); + constexpr float Cmax = Cest * (1.0f + capacitorPrecision); + + // solve the equation for C (1% precision) + *newC = cSolver.solve(Tc1_us, Tc2_us, Cmin, R + Rinternal, 0.01f); + // in case something went wrong, we must be in the allowed range + *newC = clampF(Cmin, *newC, Cmax); + + return R; +} + +template +bool HellenBoardIdFinder::measureChargingTimes(int i, float & Tc1_us, float & Tc2_us) { +#if EFI_PROD_CODE + chSemReset(&state.boardId_wake, 0); + + // full charge/discharge time, and also 'timeout' time + const int Tf_us = 50000; // 50 ms is more than enough to "fully" discharge the capacitor with any two resistors used at the same time. + + // 1. Fully discharge the capacitor through both resistors (faster) + for (size_t k = 0; k < NumPins; k++) { + palClearPad(getBrainPinPort(rPins[k]), getBrainPinIndex(rPins[k])); + palSetPadMode(getBrainPinPort(rPins[k]), getBrainPinIndex(rPins[k]), PAL_MODE_OUTPUT_PUSHPULL); + } + // wait max. time because we don't know the resistor values yet + chThdSleepMicroseconds(Tf_us); + + // use one pin as an charge/discharge controlling output + state.rOutputPinPort = getBrainPinPort(rPins[i]); + state.rOutputPinIdx = getBrainPinIndex(rPins[i]); + palSetPadMode(state.rOutputPinPort, state.rOutputPinIdx, PAL_MODE_OUTPUT_PUSHPULL); + + // use another pin as an input to detect 0->1 crossings + int inputIdx = 1 - i; + state.rInputPinPort = getBrainPinPort(rPins[inputIdx]); + state.rInputPinIdx = getBrainPinIndex(rPins[inputIdx]); + // set only high-Z input mode, no pull-ups/pull-downs allowed! + palSetPadMode(state.rInputPinPort, state.rInputPinIdx, PAL_MODE_INPUT); + efiExtiEnablePin("boardId", rPins[inputIdx], PAL_EVENT_MODE_RISING_EDGE, hellenBoardIdInputCallback, (void *)&state); + + int pinState = palReadPad(state.rInputPinPort, state.rInputPinIdx); + if (pinState != 0) { + // the input pin state should be low when the capacitor is fully discharged + efiPrintf("* Board detection error!"); + return false; + } + + // 2. Start charging until the input pin triggers (V01 threshold is reached) + state.timeChargeNt = 0; + efitick_t nowNt1 = getTimeNowNt(); + palSetPad(state.rOutputPinPort, state.rOutputPinIdx); + chSemWaitTimeout(&state.boardId_wake, TIME_US2I(Tf_us)); + + // 3. At the moment, the discharging has already been started! + // Meanwhile we need to do some checks - until some pre-selected voltage is presumably reached. + + // if voltage didn't change on the input pin, then the charging didn't start, + // meaning there's no capacitor and/or resistors on these pins. + if (state.timeChargeNt <= nowNt1) { + efiPrintf("* Hellen Board ID circuitry wasn't detected! Aborting!"); + return false; + } + + // 4. calculate the first charging time + Tc1_us = NT2USF(state.timeChargeNt - nowNt1); + // We use the same 'charging time' to discharge the capacitor to some random voltage below the threshold voltage. + float Td_us = Tc1_us; + + // we can make a tiny delay adjustments to compensate for the code execution overhead (every usec matters!) + efitick_t nowNt2 = getTimeNowNt(); + float TdAdj_us = NT2USF(nowNt2 - state.timeChargeNt); + + // 5. And now just wait for the rest of the discharge process... + // We cannot use chThdSleepMicroseconds() here because we need more precise delay + gptPolledDelay(&HELLEN_BOARD_ID_GPTDEVICE, Td_us - TdAdj_us); + + // the input pin state should be low when the capacitor is discharged to Vl + pinState = palReadPad(state.rInputPinPort, state.rInputPinIdx); + + // 6. And immediately begin charging again until the threshold voltage is reached! + state.timeChargeNt = 0; + palSetPad(state.rOutputPinPort, state.rOutputPinIdx); + + // Wait for the charging completion + efitick_t nowNt3 = getTimeNowNt(); + chSemReset(&state.boardId_wake, 0); + chSemWaitTimeout(&state.boardId_wake, TIME_US2I(Tf_us)); + + // 7. calculate the second charge time + Tc2_us = NT2USF(state.timeChargeNt - nowNt3); + +#ifdef HELLEN_BOARD_ID_DEBUG + efitick_t nowNt4 = getTimeNowNt(); + efiPrintf("* dTime21 = %d", (int)(nowNt2 - nowNt1)); + efiPrintf("* dTime32 = %d", (int)(nowNt3 - nowNt2)); + efiPrintf("* dTime43 = %d", (int)(nowNt4 - nowNt3)); + efiPrintf("* Tc1 = %f, Tc2 = %f, Td = %f, TdAdj = %f", Tc1_us, Tc2_us, Td_us, TdAdj_us); +#endif /* HELLEN_BOARD_ID_DEBUG */ + + // sanity checks + if (pinState != 0) { + efiPrintf("* Board detection error! (Td=%f is too small)", Td_us); + return false; + } + + if (state.timeChargeNt <= nowNt3) { + efiPrintf("* Estimates are out of limit! Something went wrong. Aborting!"); + return false; + } + + efiExtiDisablePin(rPins[inputIdx]); +#endif /* EFI_PROD_CODE */ + return true; +} + +template +bool HellenBoardIdFinder::measureChargingTimesAveraged(int i, float & Tc1_us, float & Tc2_us) { + const int numTries = 3; + + Tc1_us = 0; + Tc2_us = 0; + for (int tries = 0; tries < numTries; tries++) { + // get the charging times + float Tc1i_us = 0, Tc2i_us = 0; + if (!measureChargingTimes(i, Tc1i_us, Tc2i_us)) + return false; + Tc1_us += Tc1i_us; + Tc2_us += Tc2i_us; + } + + // averaging + Tc1_us /= numTries; + Tc2_us /= numTries; + + return true; +} + + +int detectHellenBoardId() { + int boardId = 0; +#if EFI_PROD_CODE + efiPrintf("Starting Hellen Board ID detection..."); + efitick_t beginNt = getTimeNowNt(); + + // Hellen boards use GPIOF_0 and GPIOF_1. + const int numPins = 2; + brain_pin_e rPins[numPins] = { GPIOF_0, GPIOF_1 }; + + // We start from the estimated capacitance, but the real one can be +-10% + float C = HELLEN_BOARD_ID_CAPACITOR; + + // we need to find the resistor values connected to the mcu pins and to the capacitor. + float R[numPins] = { 0 }; + int rIdx[numPins] = { 0 }; + + HellenBoardIdFinder finder(rPins); + + // init some ChibiOs objects + chSemObjectInit(&finder.state.boardId_wake, 0); + static constexpr GPTConfig gptCfg = { 1000000 /* 1 MHz timer clock.*/, NULL, 0, 0 }; + gptStart(&HELLEN_BOARD_ID_GPTDEVICE, &gptCfg); + + // R1 is the first, R2 is the second + for (int i = 0; i < numPins; i++) { +#ifdef HELLEN_BOARD_ID_DEBUG + efiPrintf("*** Resistor R%d...", i + 1); +#endif /* HELLEN_BOARD_ID_DEBUG */ + + float Tc1_us = 0, Tc2_us = 0; + // We need several measurements for each resistor to increase the presision. + // But if any of the measurements fails, then abort! + if (!finder.measureChargingTimesAveraged(i, Tc1_us, Tc2_us)) + break; + + // Now roughly estimate the resistor value using the approximate threshold voltage. + float Rest = finder.calcEstimatedResistance(Tc1_us, C); + // check if we are inside the range + if (Rest < 300.0f || Rest > 15000.0f) { + efiPrintf("* Unrealistic estimated resistor value (%f)! Aborting!", Rest); + break; + } + + // for the first resistor, we test only "major" values because we don't know the exact capacitance yet + bool testOnlyMajorSeries = (i == 0); + + float Rmeasured, newC; + // Now calculate the R and C + R[i] = finder.calc(Tc1_us, Tc2_us, Rest, C, testOnlyMajorSeries, &Rmeasured, &newC, &rIdx[i]); + C = newC; + +#ifdef HELLEN_BOARD_ID_DEBUG + efiPrintf("* R = %f, Rmeasured = %f, Rest = %f, Creal = %f", R[i], Rmeasured, Rest, C); +#endif /* HELLEN_BOARD_ID_DEBUG */ + } + + // in case the process was aborted + for (size_t k = 0; k < numPins; k++) { + efiExtiDisablePin(rPins[k]); + // release the pins + palSetPadMode(getBrainPinPort(rPins[k]), getBrainPinIndex(rPins[k]), PAL_MODE_RESET); + } + + gptStop(&HELLEN_BOARD_ID_GPTDEVICE); + + efitick_t endNt = getTimeNowNt(); + int elapsed_Ms = US2MS(NT2US(endNt - beginNt)); + + boardId = HELLEN_GET_BOARD_ID(rIdx[0], rIdx[1]); + efiPrintf("* RESULT: BordId = %d, R1 = %.0f, R2 = %.0f (Elapsed time: %d ms)", boardId, R[0], R[1], elapsed_Ms); +#endif /* EFI_PROD_CODE */ + return boardId; +} diff --git a/firmware/config/boards/hellen/hellen_board_id.h b/firmware/config/boards/hellen/hellen_board_id.h new file mode 100644 index 0000000000..d27c55e03d --- /dev/null +++ b/firmware/config/boards/hellen/hellen_board_id.h @@ -0,0 +1,77 @@ +/** + * @file boards/hellen/hellen_board_id.h + * @brief Board-Id detector for Hellen boards + * + * @author andreika + * @author Andrey Belomutskiy, (c) 2012-2022 + */ + +#pragma once + +// this is used by the detection method and should be visible to the interrupt handler (hellenBoardIdInputCallback) +class HellenBoardIdFinderState +{ +public: + efitick_t timeChargeNt = 0; + + ioportid_t rOutputPinPort; + int rOutputPinIdx; + ioportid_t rInputPinPort; + int rInputPinIdx; + +#if EFI_PROD_CODE + semaphore_t boardId_wake; +#endif /* EFI_PROD_CODE */ +}; + +// We need to solve the following equation for R or C: +// X^Td - X^(Tc1+Td) + X^(Tc2-Tc1) - 1 = 0 +// where: X = exp(-1/(RC)) +class HellenBoardIdSolver +{ +public: + float fx(float x) { + return exp(k1 / x) - exp(k2 / x) + exp(k3 / x) - 1.0; + } + + // first-order derivative + float dfx(float x) { + return (-1.0f / (x * x)) * (k1 * exp(k1 / x) - k2 * exp(k2 / x) + k3 * exp(k3 / x)); + } + + // Newton numerical method (x is R and y is C, or vice-versa) + float solve(float Tc1, float Tc2, float x0, float y, float deltaX); + +private: + // exponential function coefs (see solve()) + float k1, k2, k3; +}; + + +class HellenBoardIdFinderBase +{ +public: + float calc(float Tc1_us, float Tc2_us, float Rest, float C, bool testOnlyMajorSeries, float *Rmeasured, float *Cest, int *rIdx); + + float findClosestResistor(float R, bool testOnlyMajorSeries, int *rIdx); + float calcEstimatedResistance(float Tc1_us, float C); + +public: + HellenBoardIdFinderState state; +}; + +template +class HellenBoardIdFinder : public HellenBoardIdFinderBase +{ +public: + HellenBoardIdFinder(brain_pin_e (&rP)[NumPins]) : rPins(rP) {} + + // R1 or R2 + bool measureChargingTimes(int i, float & Tc1_us, float & Tc2_us); + bool measureChargingTimesAveraged(int i, float & Tc1_us, float & Tc2_us); + +public: + brain_pin_e (&rPins)[NumPins]; + HellenBoardIdFinderState state; +}; + diff --git a/firmware/config/boards/hellen/hellen_board_id_resistors.h b/firmware/config/boards/hellen/hellen_board_id_resistors.h new file mode 100644 index 0000000000..7ccdf1fe0d --- /dev/null +++ b/firmware/config/boards/hellen/hellen_board_id_resistors.h @@ -0,0 +1,14 @@ +// +// was generated automatically by Hellen Board-ID generation tool gen_hellen_board_id.jar +// + +// major_idx = 0..15 +#define HELLEN_BOARD_ID_MAJOR_RESISTORS 510, 620, 750, 1000, 1200, 1500, 1800, 2200, 2700, 3300, 3900, 4700, 5600, 6800, 8200, 10000, +// minor_idx = 0..12 +#define HELLEN_BOARD_ID_MINOR_RESISTORS 560, 680, 820, 1100, 1200, 2000, 2400, 3000, 3600, 4300, 5100, 6200, 7500, + +// C = 1uF +#define HELLEN_BOARD_ID_CAPACITOR 1.0f + +// R1_IDX = 0..15, R2_IDX = 0..28 (max. 464 boardIds) +#define HELLEN_GET_BOARD_ID(R1_IDX, R2_IDX) ((R1_IDX) * 100 + (R2_IDX)) diff --git a/firmware/config/boards/hellen/hellen_common.cpp b/firmware/config/boards/hellen/hellen_common.cpp index 153d71e36f..358fa7e1ef 100644 --- a/firmware/config/boards/hellen/hellen_common.cpp +++ b/firmware/config/boards/hellen/hellen_common.cpp @@ -33,7 +33,7 @@ void setHellen176LedPins() { } // this should be called before setHellenXXXLedPins() -void detectHellenBoardType() { +void detectHellenMcuType() { // we test the red LED1 pin because the red LED used has the smallest voltage drop, // and thus can be detected more accurately static const brain_pin_e led1Pins[2] = { @@ -70,3 +70,8 @@ void detectHellenBoardType() { efiPrintf("* Cannot detect Hellen mcu module!"); } } + +void detectHellenBoardType() { + detectHellenMcuType(); + detectHellenBoardId(); +} diff --git a/firmware/config/boards/hellen_meta.h b/firmware/config/boards/hellen_meta.h index deee6b1f4f..cca5e72d90 100644 --- a/firmware/config/boards/hellen_meta.h +++ b/firmware/config/boards/hellen_meta.h @@ -13,6 +13,7 @@ void setHellenDefaultVrThresholds(); void setHellen144LedPins(); void setHellen176LedPins(); +int detectHellenBoardId(); void detectHellenBoardType(); // stm32 UART8 diff --git a/firmware/hw_layer/hardware.cpp b/firmware/hw_layer/hardware.cpp index 749eccb2d6..93b3201d46 100644 --- a/firmware/hw_layer/hardware.cpp +++ b/firmware/hw_layer/hardware.cpp @@ -428,6 +428,11 @@ void initHardwareNoConfig() { #if EFI_FILE_LOGGING initEarlyMmcCard(); #endif // EFI_FILE_LOGGING + +#if HAL_USE_PAL && EFI_PROD_CODE + // this should be initialized before detectBoardType() + efiExtiInit(); +#endif // HAL_USE_PAL } void stopHardware() { @@ -475,10 +480,6 @@ __attribute__((weak)) void boardInitHardware() { } __attribute__((weak)) void setPinConfigurationOverrides() { } void initHardware() { -#if HAL_USE_PAL && EFI_PROD_CODE - efiExtiInit(); -#endif // HAL_USE_PAL - #if EFI_HD44780_LCD lcd_HD44780_init(); if (hasFirmwareError()) diff --git a/firmware/util/efitime.h b/firmware/util/efitime.h index a183d21a61..daaeaa79ad 100644 --- a/firmware/util/efitime.h +++ b/firmware/util/efitime.h @@ -34,6 +34,7 @@ // And back #define NT2US(x) ((x) / US_TO_NT_MULTIPLIER) +#define NT2USF(x) (((float)(x)) / US_TO_NT_MULTIPLIER) // milliseconds to ticks #define MS2NT(msTime) US2NT(MS2US(msTime)) diff --git a/unit_tests/Makefile b/unit_tests/Makefile index fe8d8bbb50..95c36a6713 100644 --- a/unit_tests/Makefile +++ b/unit_tests/Makefile @@ -29,6 +29,7 @@ CPPSRC += $(ALLCPPSRC) \ $(DEVELOPMENT_DIR)/engine_sniffer.cpp \ $(PROJECT_DIR)/console/binary/tooth_logger.cpp \ $(PROJECT_DIR)/console/binary_log/log_field.cpp \ + $(PROJECT_DIR)/config/boards/hellen/hellen_board_id.cpp \ $(PROJECT_DIR)/../unit_tests/logicdata.cpp \ $(PROJECT_DIR)/../unit_tests/main.cpp \ $(PROJECT_DIR)/../unit_tests/global_mocks.cpp \ @@ -38,6 +39,7 @@ INCDIR += \ $(PCH_DIR) \ $(UNIT_TESTS_DIR) \ $(ALLINC) \ + $(PROJECT_DIR)/config/boards/hellen \ $(UNIT_TESTS_DIR)/test_data_structures \ $(UNIT_TESTS_DIR)/chibios-mock \ $(UNIT_TESTS_DIR)/tests \ diff --git a/unit_tests/tests/test_hellen_board_id.cpp b/unit_tests/tests/test_hellen_board_id.cpp new file mode 100644 index 0000000000..f1427d0741 --- /dev/null +++ b/unit_tests/tests/test_hellen_board_id.cpp @@ -0,0 +1,56 @@ +/* + * @file test_hellen_board_id.cpp + * + * @date Jan 20, 2022 + * @author andreika + * @author Andrey Belomutskiy, (c) 2012-2022 + */ + +#include "pch.h" +#include "gtest/gtest.h" +#include "hellen_meta.h" +#include "digital_input_exti.h" + +#include "hellen_board_id.h" + +TEST(hellen_board_id, testNewtonSolver) { + // let's prove that our formula is independent of the threshold voltage: + HellenBoardIdSolver solver; + // 1.5V threshold + EXPECT_NEAR(1100, solver.solve(666.74938f, 353.32522f, 1000.0f, 1.0f, 1.0f), 0.001); + // 2.5V threshold + EXPECT_NEAR(1100, solver.solve(1558.773f, 1335.563f, 1000.0f, 1.0f, 1.0f), 0.001); +} + +TEST(hellen_board_id, testClosestResistor) { + HellenBoardIdFinderBase finder; + int rIdx; + // use only major series + EXPECT_FLOAT_EQ(1000, finder.findClosestResistor(876, true, &rIdx)); + EXPECT_FLOAT_EQ(1000, finder.findClosestResistor(1100, true, &rIdx)); + EXPECT_FLOAT_EQ(1200, finder.findClosestResistor(1100+1, true, &rIdx)); + // use full series + EXPECT_FLOAT_EQ(1000, finder.findClosestResistor(1050, false, &rIdx)); + EXPECT_FLOAT_EQ(1100, finder.findClosestResistor(1050+1, false, &rIdx)); + EXPECT_FLOAT_EQ(1100, finder.findClosestResistor(1149, false, &rIdx)); + EXPECT_FLOAT_EQ(1200, finder.findClosestResistor(1150, false, &rIdx)); + + EXPECT_FLOAT_EQ(510, finder.findClosestResistor(0, true, &rIdx)); + ASSERT_EQ(0, rIdx); +} + +TEST(hellen_board_id, testEstimatedResistor) { + HellenBoardIdFinderBase finder; + EXPECT_NEAR(10000, finder.calcEstimatedResistance(6931.4718055995f, 1.0f), 0.001); +} + +TEST(hellen_board_id, testCalc) { + HellenBoardIdFinderBase finder; + float Rmeasured, newC; + int rIdx; + float R = finder.calc(1024.714f, 724.639555f, 1099.0f, 1.0f, false, &Rmeasured, &newC, &rIdx); + EXPECT_NEAR(1100, R, 0.001); + EXPECT_NEAR(1099.998779, Rmeasured, 0.001); + EXPECT_NEAR(0.973396897, newC, 0.001); + ASSERT_EQ(19, rIdx); +} diff --git a/unit_tests/tests/tests.mk b/unit_tests/tests/tests.mk index af2886316f..cef5c53eda 100644 --- a/unit_tests/tests/tests.mk +++ b/unit_tests/tests/tests.mk @@ -85,6 +85,7 @@ TESTS_SRC_CPP = \ tests/test_limp.cpp \ tests/trigger/test_all_triggers.cpp \ tests/test_can_serial.cpp \ + tests/test_hellen_board_id.cpp \ tests/sensor/test_frequency_sensor.cpp \ tests/sensor/test_turbocharger_speed_converter.cpp \ tests/sensor/test_vehicle_speed_converter.cpp \