GCC Code Coverage Report


Directory: ./
File: firmware/controllers/algo/dynoview.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 93.8% 90 0 96
Functions: 100.0% 7 0 7
Branches: 73.3% 22 0 30
Decisions: 79.2% 19 - 24

Line Branch Decision Exec Source
1 /*
2 * @file dynoview.cpp
3 *
4 * @date Jan 05, 2025
5 * @author Alexey Ershov, (c) 2012-2025
6 */
7
8 #include "pch.h"
9
10 #if EFI_DYNO_VIEW
11 #include "dynoview.h"
12 #include "fuel_math.h"
13
14 1172 void DynoView::init()
15 {
16
2/2
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 584 times.
2/2
✓ Decision 'true' taken 588 times.
✓ Decision 'false' taken 584 times.
1172 if (isInitialized) {
17 588 return;
18 }
19 584 isInitialized = true;
20
21 //config->dynoSaeBaro = Sensor::get(SensorType::BarometricPressure).value_or(config->dynoSaeBaro);
22
23 584 wheelOverallDiameterMm = (uint16_t)((float)config->dynoCarWheelDiaInch * 25.4f + (float)config->dynoCarWheelTireWidthMm * (float)config->dynoCarWheelAspectRatio * 0.01f * 2.0f);
24
25 584 saeVaporPressure = 6.1078f * pow(10.0f, (7.5f * (float)config->dynoSaeTemperatureC) / (237.3f + (float)config->dynoSaeTemperatureC)) * .02953f * ((float)config->dynoSaeRelativeHumidity / 100.0f);
26 584 saeBaroMmhg = 29.23f * (config->dynoSaeBaro / 100.0f);
27 584 saeBaroCorrectionFactor = 29.23f / (saeBaroMmhg - saeVaporPressure);
28 584 saeTempCorrectionFactor = pow((((float)config->dynoSaeTemperatureC + C_K_OFFSET) / 298.0f), 0.5f);
29 584 saeCorrectionFactor = 1.176f * (saeBaroCorrectionFactor * saeTempCorrectionFactor) - .176f;
30
31 584 reset();
32 }
33
34 1172 void DynoView::update()
35 {
36 1172 init();
37
38 1172 float rpm = Sensor::getOrZero(SensorType::Rpm);
39 1172 rpm = efiRound(rpm, 1.0);
40 1172 int intRpm = (int)rpm;
41
42 1172 float tps = Sensor::getOrZero(SensorType::Tps1);
43
44
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 806 times.
2/2
✓ Decision 'true' taken 366 times.
✓ Decision 'false' taken 806 times.
1172 if(intRpm > 0) {
45 366 efitimeus_t timeStamp = getTimeNowUs();
46 366 float timeInSec = (float)(timeStamp) / US_PER_SECOND;
47
48 366 onRpm(intRpm, timeInSec, tps);
49 }
50 1172 }
51
52 784 void DynoView::reset()
53 {
54 784 dynoViewPointPrev.rpm = -1;
55 784 dynoViewPointPrev.time = -1;
56 784 dynoViewPointPrev.tps = -1;
57 784 count = 0;
58 784 count_rpm = 0;
59 784 currentTorque = 0;
60 784 currentHP = 0;
61 784 }
62
63 366 bool DynoView::onRpm(int rpm, float time, float tps)
64 {
65
3/4
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 166 times.
2/2
✓ Decision 'true' taken 200 times.
✓ Decision 'false' taken 166 times.
366 if(tps < dyno_view_tps_min_for_run || dynoViewPointPrev.tps - tps > dyno_view_tps_diff_to_reset_run) {
66 200 reset();
67 200 return false;
68 }
69
70
3/4
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
2/2
✓ Decision 'true' taken 162 times.
✓ Decision 'false' taken 4 times.
166 if (dynoViewPointPrev.rpm > 0 && dynoViewPointPrev.time > 0)
71 {
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 162 times.
162 if(abs(rpm - prev_rpm) < 1) {
73 return false;
74 }
75 162 prev_rpm = rpm;
76
77 // more smoothly
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 162 times.
162 if((time - dynoViewPointPrev.time) < dyno_view_log_time_smooth_sec)
79 {
80 return false;
81 }
82
83 162 int rpmDiffSmooth = abs(rpm - dynoViewPointPrev.rpm);
84
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 162 times.
162 if(rpmDiffSmooth < dyno_view_rpm_diff_smooth) {
86 return false;
87 }
88
89 162 DynoView::move(dyno_view_window_size_rpm, tail_rpm);
90 162 tail_rpm[0] = rpm;
91
92 162 count_rpm++;
93 162 int accumulate_window_size = std::min(count_rpm, dyno_view_window_size_rpm);
94 162 dynoViewPoint.rpm = (int)accumulate_window(accumulate_window_size, tail_rpm);
95
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 162 times.
162 if(dynoViewPoint.rpm + dyno_view_rpm_fall_to_reset_run < dynoViewPointPrev.rpm)
97 {
98 reset();
99 return false;
100 }
101
102 162 int rpmDiffStep = abs(dynoViewPoint.rpm - dynoViewPointPrev.rpm);
103
104
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 140 times.
2/2
✓ Decision 'true' taken 22 times.
✓ Decision 'false' taken 140 times.
162 if (rpmDiffStep < config->dynoRpmStep)
105 {
106 22 return false;
107 }
108
109 140 } else {
110 4 dynoViewPoint.rpm = rpm;
111 }
112
113 //dynoViewPoint.rpm = rpm;
114 144 dynoViewPoint.time = time;
115 144 dynoViewPoint.tps = tps;
116
117 144 dynoViewPoint.engineRps = dynoViewPoint.rpm / 60.0;
118 144 dynoViewPoint.axleRps = dynoViewPoint.engineRps / (config->dynoCarGearPrimaryReduction * config->dynoCarGearRatio * config->dynoCarGearFinalDrive);
119 144 dynoViewPoint.vMs = dynoViewPoint.axleRps * (wheelOverallDiameterMm / 1000.f) * 3.1416;
120 144 dynoViewPoint.mph = dynoViewPoint.vMs * 2.2369363;
121
122
3/4
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 140 times.
✗ Branch 3 not taken.
2/2
✓ Decision 'true' taken 140 times.
✓ Decision 'false' taken 4 times.
144 if (dynoViewPointPrev.rpm > 0 && dynoViewPointPrev.time > 0)
123 {
124 140 dynoViewPoint.distanceM = ((dynoViewPoint.vMs + dynoViewPointPrev.vMs) / 2.0) * (dynoViewPoint.time - dynoViewPointPrev.time);
125 140 dynoViewPoint.aMs2 = (dynoViewPoint.vMs - dynoViewPointPrev.vMs) / (dynoViewPoint.time - dynoViewPointPrev.time);
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 140 times.
140 if(dynoViewPoint.aMs2 < 0) {
127 dynoViewPoint.aMs2 = 0;
128 }
129 140 dynoViewPoint.forceN = (config->dynoCarCargoMassKg + config->dynoCarCarMassKg) * dynoViewPoint.aMs2;
130 140 dynoViewPoint.forceDragN = 0.5 * airDensityKgM3 * (dynoViewPoint.vMs * dynoViewPoint.vMs) * config->dynoCarFrontalAreaM2 * config->dynoCarCoeffOfDrag;
131
132 140 dynoViewPoint.forceDragN = dynoViewPoint.forceDragN * saeCorrectionFactor;
133
134 140 dynoViewPoint.forceTotalN = dynoViewPoint.forceN + dynoViewPoint.forceDragN;
135 140 dynoViewPoint.torqueWheelNm = dynoViewPoint.forceTotalN * ((wheelOverallDiameterMm / 2.0) / 1000.0);
136 140 dynoViewPoint.torqueNm = dynoViewPoint.torqueWheelNm / (config->dynoCarGearPrimaryReduction * config->dynoCarGearRatio * config->dynoCarGearFinalDrive);
137 140 dynoViewPoint.torqueLbFt = dynoViewPoint.torqueNm * 0.737562;
138 140 dynoViewPoint.hp = dynoViewPoint.torqueLbFt * dynoViewPoint.rpm / 5252.0;
139
140 140 DynoView::move(dyno_view_window_size, tail_hp);
141 140 DynoView::move(dyno_view_window_size, tail_torque);
142
143 140 tail_torque[0] = dynoViewPoint.torqueNm;
144 140 tail_hp[0] = dynoViewPoint.hp;
145
146
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 112 times.
2/2
✓ Decision 'true' taken 28 times.
✓ Decision 'false' taken 112 times.
140 if(count < dyno_view_window_size) {
147 28 ++count;
148 }
149
150 140 int accumulate_window_size = std::min(count, dyno_view_window_size);
151
152 140 currentTorque = accumulate_window(accumulate_window_size, tail_torque);
153 140 currentHP = accumulate_window(accumulate_window_size, tail_hp);
154
155 140 dynoViewPointPrev = dynoViewPoint;
156 140 return true;
157 }
158
159 4 dynoViewPointPrev = dynoViewPoint;
160
161 4 return false;
162 }
163
164 523040 int getDynoviewHP() {
165 523040 return (int)engine->dynoInstance.currentHP;
166 }
167
168 523040 int getDynoviewTorque() {
169 523040 return (int)engine->dynoInstance.currentTorque;
170 }
171
172 /**
173 * Periodic update function called from SlowCallback.
174 */
175 1085 void updateDynoView() {
176 1085 engine->dynoInstance.update();
177 1085 }
178
179 #endif /* EFI_DYNO_VIEW */
180