rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
malfunction_indicator.cpp
Go to the documentation of this file.
1/**
2 * @file malfunction_indicator.cpp
3 * @brief We can blink out OBD-II error codes using Malfunction Indicator Light (MIL)
4 *
5 *
6 * @date Dec 20, 2013
7 * @author Konstantin Nikonenko
8 * @author Andrey Belomutskiy, (c) 2012-2020
9 * we show 4 digit error code - 1,5sec * (4xxx+1) digit + 0,4sec * (x3xxx+1) + ....
10 * ATTENTION!!! 0 = 1 blink, 1 = 2 blinks, ...., 9 = 10 blinks
11 * sequence is the constant!!!
12 *
13 *
14 * This file is part of rusEfi - see http://rusefi.com
15 *
16 * rusEfi is free software; you can redistribute it and/or modify it under the terms of
17 * the GNU General Public License as published by the Free Software Foundation; either
18 * version 3 of the License, or (at your option) any later version.
19 *
20 * rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
21 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License along with this program.
25 * If not, see <http://www.gnu.org/licenses/>.
26 */
27
28#include "pch.h"
29
30#if EFI_MALFUNCTION_INDICATOR
31#include "malfunction_central.h"
33
35
36#define TEST_MIL_CODE FALSE
37
38#define MFI_LONG_BLINK 1500
39#define MFI_SHORT_BLINK 400
40#define MFI_BLINK_SEPARATOR 400
41#define MFI_CHECKENGINE_LIGHT 10000
42
43static void blink_digits(int digit, int duration) {
44 for (int iter = 0; iter < digit; iter++) {
45 // todo: why we set LOW and then HIGH? not the other way around?
47 chThdSleepMilliseconds(duration);
49 chThdSleepMilliseconds(MFI_BLINK_SEPARATOR);
50 }
51}
52
53// calculate how many digits our code have
54static int DigitLength(int digit) {
55 int i = 0;
56 while (digit > 0) {
57 digit = digit / 10;
58 ++i;
59 }
60 return i;
61}
62
63// display code
64static void DisplayErrorCode(int length, int code) {
65 // todo: I suggest we use 'itoa' method to simplify this logic
66 for (int iter = length - 1; iter >= 0; iter--) {
67 int ourDigit = (int) efiPow10(iter); // 10^0 = 1, 10^1 = 10, 10^2=100, 10^3 = 1000, ....
68 int digit = 1; // as we remember "0" we show as one blink
69 while (code >= ourDigit) {
70 code = code - ourDigit;
71 digit++;
72 }
73 if (iter % 2 == 0)
74 blink_digits(digit, MFI_SHORT_BLINK); // even 2,0 - long blink
75 else
76 blink_digits(digit, MFI_LONG_BLINK); // odd 3,1 - short blink
77 }
78}
79
80class MILController : public PeriodicController<UTILITY_THREAD_STACK_SIZE> {
81public:
82 MILController() : PeriodicController("MFIndicator") { }
83private:
84 void PeriodicTask(efitick_t nowNt) override {
85 UNUSED(nowNt);
86
87 assertStackVoid("MIL", ObdCode::STACK_USAGE_MIL, EXPECTED_REMAINING_STACK);
88#if EFI_SHAFT_POSITION_INPUT
89 if (nowNt - engine->triggerCentral.triggerState.mostRecentSyncTime < MS2NT(500)) {
91 chThdSleepMilliseconds(500);
93 }
94#endif // EFI_SHAFT_POSITION_INPUT
95
96 static error_codes_set_s localErrorCopy;
97 // todo: why do I not see this on a real vehicle? is this whole blinking logic not used?
98 getErrorCodes(&localErrorCopy);
99 for (int p = 0; p < localErrorCopy.count; p++) {
100 // Calculate how many digits in this integer and display error code from start to end
101 int code = (int)localErrorCopy.error_codes[p];
103 }
104 }
105};
106
107static MILController instance;
108
109#if TEST_MIL_CODE
110static void testMil() {
111 addError(ObdCode::OBD_Engine_Coolant_Temperature_Circuit_Malfunction);
112 addError(ObdCode::OBD_Intake_Air_Temperature_Circuit_Malfunction);
113}
114#endif /* TEST_MIL_CODE */
115
119
121 if (!isMilEnabled()) {
122 return;
123 }
124 instance.setPeriod(10 /*ms*/);
125 instance.start();
126
127#if TEST_MIL_CODE
128 addConsoleAction("testmil", testMil);
129#endif /* TEST_MIL_CODE */
130}
131
132#endif /* EFI_MALFUNCTION_INDICATOR */
uint8_t code
Definition bluetooth.cpp:40
TriggerCentral triggerCentral
Definition engine.h:318
RegisteredOutputPin checkEnginePin
Definition efi_gpio.h:118
void setValue(const char *msg, int logicValue, bool isForce=false)
Definition efi_gpio.cpp:604
Base class for a controller that needs to run periodically to perform work.
virtual void PeriodicTask(efitick_t nowNt)=0
Called periodically. Override this method to do work for your controller.
PrimaryTriggerDecoder triggerState
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
EnginePins enginePins
Definition efi_gpio.cpp:24
int efiPow10(int param)
Definition efilib.cpp:111
static EngineAccessor engine
Definition engine.h:413
static constexpr engine_configuration_s * engineConfiguration
UNUSED(samplingTimeSeconds)
void getErrorCodes(error_codes_set_s *copy)
Copies the current set of errors into the specified buffer.
void addError(ObdCode errorCode)
Adds an error code into the set of current errors. The error code is placed into the fixed-size data ...
This data structure holds current malfunction codes.
static MILController instance
static void blink_digits(int digit, int duration)
static void testMil()
void initMalfunctionIndicator(void)
static void DisplayErrorCode(int length, int code)
static int DigitLength(int digit)
bool isMilEnabled()
We can blink out OBD-II error codes using Malfunction Indicator Light (MIL)
@ STACK_USAGE_MIL
bool isBrainPinValid(brain_pin_e brainPin)
ObdCode error_codes[MAX_ERROR_CODES_COUNT]