rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
logic_analyzer.cpp
Go to the documentation of this file.
1/**
2 * @file logic_analyzer.cpp
3 * @brief Initialization of Input Capture pins used for rusEfi console sniffer
4 *
5 * This file is responsible for sniffing of external digital signals and registering
6 * these digital events in WaveChart used by the Engine Sniffer tab of rusEfi Console.
7 *
8 * this is rusEfi build-in logic analyzer
9 *
10 * @date Jan 7, 2013
11 * @author Andrey Belomutskiy, (c) 2012-2020
12 */
13
14#include "pch.h"
15#include "logic_analyzer.h"
16
17#include "eficonsole.h"
18#include "trigger_central.h"
19#include "os_util.h"
20#include "rpm_calculator.h"
21#include "engine_sniffer.h"
22#include "digital_input_exti.h"
23
24#if EFI_LOGIC_ANALYZER
25
26#define CHART_RESET_DELAY 1
27
28/**
29 * Difference between current 1st trigger event and previous 1st trigger event.
30 */
31static volatile uint32_t engineCycleDurationUs;
32static volatile efitimeus_t previousEngineCycleTimeUs = 0;
33
34class WaveReader {
35public:
36 void onFallEvent();
37
38 ioline_t line = 0;
39
40 int laIndex;
41 volatile int fallEventCounter = 0;
42 volatile int riseEventCounter = 0;
43
44 int currentRevolutionCounter = 0;
45
46 /**
47 * Total ON time during last engine cycle
48 */
49 efitimeus_t prevTotalOnTimeUs = 0;
50
51 efitimeus_t totalOnTimeAccumulatorUs = 0;
52
53 volatile efitimeus_t lastActivityTimeUs = 0; // timestamp in microseconds ticks
54 /**
55 * time of signal fall event, in microseconds
56 */
57 volatile efitimeus_t periodEventTimeUs = 0;
58 volatile efitimeus_t widthEventTimeUs = 0; // time of signal rise in microseconds
59
60 volatile efitimeus_t signalPeriodUs = 0; // period between two signal rises in microseconds
61
62 /**
63 * offset from engine cycle start in microseconds
64 */
65 volatile efitimeus_t waveOffsetUs = 0;
66 volatile efitimeus_t last_wave_low_widthUs = 0; // time period in systimer ticks
67 volatile efitimeus_t last_wave_high_widthUs = 0; // time period in systimer ticks
68};
69
70static WaveReader readers[LOGIC_ANALYZER_CHANNEL_COUNT];
71
72static void riseCallback(WaveReader *reader) {
73 efitimeus_t nowUs = getTimeNowUs();
74 reader->riseEventCounter++;
75 reader->lastActivityTimeUs = nowUs;
76 assertIsrContext(ObdCode::CUSTOM_ERR_6670);
78
79 uint32_t width = nowUs - reader->periodEventTimeUs;
80 reader->last_wave_low_widthUs = width;
81
82 reader->signalPeriodUs = nowUs - reader->widthEventTimeUs;
83 reader->widthEventTimeUs = nowUs;
84}
85
86void WaveReader::onFallEvent() {
87 efitimeus_t nowUs = getTimeNowUs();
88 fallEventCounter++;
89 lastActivityTimeUs = nowUs;
90 assertIsrContext(ObdCode::CUSTOM_ERR_6670);
92
93 efitimeus_t width = nowUs - widthEventTimeUs;
94 last_wave_high_widthUs = width;
95
96#if EFI_SHAFT_POSITION_INPUT
97 int revolutionCounter = getRevolutionCounter();
98#else
99 int revolutionCounter = 0;
100#endif
101
102 totalOnTimeAccumulatorUs += width;
103 if (currentRevolutionCounter != revolutionCounter) {
104 /**
105 * We are here in case of a new engine cycle
106 */
107 currentRevolutionCounter = revolutionCounter;
108 prevTotalOnTimeUs = totalOnTimeAccumulatorUs;
109 totalOnTimeAccumulatorUs = 0;
110
111 waveOffsetUs = nowUs - previousEngineCycleTimeUs;
112 }
113
114 periodEventTimeUs = nowUs;
115}
116
117void logicAnalyzerCallback(void* arg, efitick_t /*stamp*/) {
118 WaveReader* instance = reinterpret_cast<WaveReader*>(arg);
119
120 bool rise = palReadLine(instance->line) == PAL_HIGH;
121
122 if (rise) {
124 } else {
125 instance->onFallEvent();
126 }
127}
128
129static void initWave(size_t index) {
131
132 efiAssertVoid(ObdCode::CUSTOM_ERR_6655, index < efi::size(readers), "too many ICUs");
133 WaveReader *reader = &readers[index];
134
135 if (!isBrainPinValid(brainPin)) {
136 /**
137 * in case we are running, and we select none for a channel that was running,
138 * this way we ensure that we do not get false report from that channel
139 **/
140 reader->line = 0;
141 return;
142 }
143
144 reader->laIndex = index;
145
146 reader->line = PAL_LINE(getHwPort("logic", brainPin), getHwPin("logic", brainPin));
147
148 efiExtiEnablePin("logic", brainPin, PAL_EVENT_MODE_BOTH_EDGES, logicAnalyzerCallback, (void*)reader);
149
150 efiPrintf("wave%d input on %s", index, hwPortname(brainPin));
151}
152
153void waTriggerEventListener(trigger_event_e ckpSignalType, uint32_t index, efitick_t edgeTimestamp) {
154 (void)ckpSignalType;
155 if (index != 0) {
156 return;
157 }
158
159 efitimeus_t nowUs = NT2US(edgeTimestamp);
162}
163
164static float getSignalOnTime(int index) {
165 WaveReader& reader = readers[index];
166
167 if (getTimeNowUs() - reader.lastActivityTimeUs > 4 * US_PER_SECOND) {
168 return 0.0f; // dwell time has expired
169 }
170 return reader.last_wave_high_widthUs / 1000.0f;
171}
172
173static efitimeus_t getWaveOffset(int index) {
174 return readers[index].waveOffsetUs;
175}
176
177static float getSignalPeriodMs(int index) {
178 return readers[index].signalPeriodUs / 1000.0f;
179}
180
181static void reportWave(Logging *logging, int index) {
182 if (readers[index].line == 0) {
183 return;
184 }
185
186// int counter = getEventCounter(index);
187// debugInt2(logging, "ev", index, counter);
188
189 float dwellMs = getSignalOnTime(index);
190 float periodMs = getSignalPeriodMs(index);
191
192 logging->appendPrintf("duty%d%s", index, LOG_DELIMITER);
193 logging->appendFloat(100.0f * dwellMs / periodMs, 2);
194 logging->appendPrintf("%s", LOG_DELIMITER);
195
196 /**
197 * that's the ON time of the LAST signal
198 */
199 logging->appendPrintf("dwell%d%s", index, LOG_DELIMITER);
200 logging->appendFloat(dwellMs, 2);
201 logging->appendPrintf("%s", LOG_DELIMITER);
202
203 /**
204 * that's the total ON time during the previous engine cycle
205 */
206 logging->appendPrintf("total_dwell%d%s", index, LOG_DELIMITER);
207 logging->appendFloat(readers[index].prevTotalOnTimeUs / 1000.0f, 2);
208 logging->appendPrintf("%s", LOG_DELIMITER);
209
210 logging->appendPrintf("period%d%s", index, LOG_DELIMITER);
211 logging->appendFloat(periodMs, 2);
212 logging->appendPrintf("%s", LOG_DELIMITER);
213
214 efitimeus_t offsetUs = getWaveOffset(index);
216 if (rpm != 0) {
217 float oneDegreeUs = getOneDegreeTimeUs(rpm);
218
219 logging->appendPrintf("advance%d%s", index, LOG_DELIMITER);
220 float angle = (offsetUs / oneDegreeUs) - tdcPosition();
221 wrapAngle(angle, "waveAn", ObdCode::CUSTOM_ERR_6564);
222 logging->appendFloat(angle, 3);
223 logging->appendPrintf("%s", LOG_DELIMITER);
224 }
225}
226
227void printWave(Logging *logging) {
228 reportWave(logging, 0);
229 reportWave(logging, 1);
230}
231
232void showWaveInfo(void) {
233 efiPrintf("logic input #1: %d/%d", readers[0].fallEventCounter, readers[0].riseEventCounter);
234}
235
237 if (hasFirmwareError()) {
238 return;
239 }
240
241 addConsoleAction("waveinfo", showWaveInfo);
242}
243
245 for (size_t index = 0; index < LOGIC_ANALYZER_CHANNEL_COUNT; index++) {
246 initWave(index);
247 }
248}
249
251 for (int index = 0; index < LOGIC_ANALYZER_CHANNEL_COUNT; index++) {
253
254 if (isBrainPinValid(brainPin)) {
255 efiExtiDisablePin(brainPin);
256 }
257 }
258}
259
260template <typename TFreq>
261static void getChannelFreqAndDuty(int index, float& duty, TFreq& freq) {
262 if (readers[index].line == 0) {
263 duty = 0.0;
264 freq = 0;
265 } else {
266 float high = getSignalOnTime(index);
267 float period = getSignalPeriodMs(index);
268
269 if (period != 0) {
270
271 duty = (high * 1000.0f) /(period * 10.0f);
272 freq = (int)(1 / (period / 1000.0f));
273 } else {
274 duty = 0.0;
275 freq = 0;
276 }
277 }
278}
279
288
289#endif /* EFI_LOGIC_ANALYZER */
static BenchController instance
beuint32_t period
TunerStudioOutputChannels outputChannels
Definition engine.h:109
void void appendFloat(float value, int precision)
void appendPrintf(const char *fmt,...) __attribute__((format(printf
static float getOrZero(SensorType type)
Definition sensor.h:83
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
void efiExtiDisablePin(brain_pin_e brainPin)
int efiExtiEnablePin(const char *msg, brain_pin_e brainPin, uint32_t mode, ExtiCallback cb, void *cb_data)
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
Console package entry point header.
efitimeus_t getTimeNowUs()
Definition efitime.cpp:26
static EngineAccessor engine
Definition engine.h:413
engine_configuration_s & activeConfiguration
static constexpr engine_configuration_s * engineConfiguration
void addEngineSnifferLogicAnalyzerEvent(int laIndex, FrontDirection frontDirection)
rusEfi console wave sniffer
uint32_t ioline_t
Type of an I/O line.
Definition hal_pal_lld.h:88
static volatile efitimeus_t previousEngineCycleTimeUs
static WaveReader readers[LOGIC_ANALYZER_CHANNEL_COUNT]
static void riseCallback(WaveReader *reader)
static void reportWave(Logging *logging, int index)
void waTriggerEventListener(trigger_event_e ckpSignalType, uint32_t index, efitick_t edgeTimestamp)
void stopLogicAnalyzerPins()
void logicAnalyzerCallback(void *arg, efitick_t)
void startLogicAnalyzerPins()
static volatile uint32_t engineCycleDurationUs
void printWave(Logging *logging)
static void initWave(size_t index)
void showWaveInfo(void)
void initWaveAnalyzer()
void reportLogicAnalyzerToTS()
static void getChannelFreqAndDuty(int index, float &duty, TFreq &freq)
static efitimeus_t getWaveOffset(int index)
static float getSignalOnTime(int index)
static float getSignalPeriodMs(int index)
@ CUSTOM_ERR_6655
@ CUSTOM_ERR_6564
@ CUSTOM_ERR_6670
const char * hwPortname(brain_pin_e brainPin)
bool isBrainPinValid(brain_pin_e brainPin)
Shaft position sensor(s) decoder header.
trigger_event_e
brain_input_pin_e logicAnalyzerPins[LOGIC_ANALYZER_CHANNEL_COUNT]
static float duty
void wrapAngle(angle_t &angle, const char *msg, ObdCode code)