Rev 11 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 11 | Rev 12 | ||
|---|---|---|---|
| Line 1... | Line 1... | ||
| 1 | #include <cstdint> |
1 | #include <cstdint> |
| 2 | #include <assert.h> |
2 | #include <assert.h> |
| 3 | #include "libIgnTiming/timing.h" |
3 | #include "libIgnTiming/timing.h" |
| - | 4 | #include "libIgnTiming/basemap.h" |
|
| 4 | 5 | ||
| 5 | #if !defined WRITABLE_TABLE |
- | |
| 6 | #define CONST_ATTR constexpr |
- | |
| 7 | #endif |
- | |
| 8 | 6 | ||
| 9 | #if defined __cplusplus |
7 | #if defined __cplusplus |
| 10 | extern "C" |
8 | extern "C" |
| 11 | { |
9 | { |
| 12 | #endif |
10 | #endif |
| 13 | 11 | ||
| 14 | namespace |
12 | namespace |
| 15 | { |
13 | { |
| 16 | int8_t timingAdjust = 0 * TIMING_SCALE; // in TIMING_SCALE |
14 | int8_t timingAdjust = 0 * TIMING_SCALE; // in TIMING_SCALE |
| 17 | - | ||
| 18 | unsigned constexpr INTERP_SCALE = 256; |
15 | // local copy of the data structure |
| 19 | - | ||
| 20 | int constexpr TimingScale = TIMING_SCALE; |
16 | timingTable_t timingMap = baseTimingMap; |
| 21 | int16_t constexpr NO_DATA = -1; |
- | |
| 22 | 17 | ||
| 23 | int16_t constexpr MAX_ADVANCE = 50 * TIMING_SCALE; |
18 | int16_t constexpr MAX_ADVANCE = 50 * TIMING_SCALE; |
| 24 | int16_t constexpr MIN_ADVANCE = 7 * TIMING_SCALE; |
19 | int16_t constexpr MIN_ADVANCE = 7 * TIMING_SCALE; |
| 25 | 20 | ||
| 26 | // array of column headings |
- | |
| 27 | int16_t CONST_ATTR rpmMap[MAX_RPM_POINTS] = {400, 750, 1000, 1500, 2500, 3500, 4500, 6000}; |
- | |
| 28 | // column of row values - in 1000-pressure |
- | |
| 29 | int16_t CONST_ATTR vacuumMap[MAX_VACUUM_POINTS] = {0, 166, 225, 300, 700, 1000, NO_DATA, NO_DATA}; |
- | |
| 30 | uint8_t CONST_ATTR mapping[MAX_VACUUM_POINTS][MAX_RPM_POINTS] = { |
- | |
| 31 | /* Table in degrees. */ |
- | |
| 32 | /* row for 0mb = centrifugal only */ |
- | |
| 33 | {12, 7, 7, 19, 25, 29, 29, 22}, |
- | |
| 34 | /* row for 166 mB*/ |
- | |
| 35 | {12, 7, 7, 21, 27, 31, 31, 24}, |
- | |
| 36 | /* row for 225 mB */ |
- | |
| 37 | {12, 7, 7, 25, 31, 35, 35, 28}, |
- | |
| 38 | /* row for 300 mB*/ |
- | |
| 39 | {12, 7, 7, 29, 35, 39, 39, 33}, |
- | |
| 40 | /* row for 700 mB*/ |
- | |
| 41 | {12, 7, 7, 19, 25, 29, 29, 22}, |
- | |
| 42 | /* row for 1000 mB - used when pressure drops off the scale */ |
- | |
| 43 | {7, 7, 7, 7, 7, 7, 7, 7}, |
- | |
| 44 | /* unused */ |
- | |
| 45 | {0, 0, 0, 0, 0, 0, 0, 0}, |
- | |
| 46 | /* unused */ |
- | |
| 47 | {0, 0, 0, 0, 0, 0, 0, 0}, |
- | |
| 48 | /* unused */ |
- | |
| 49 | 21 | ||
| 50 | }; |
- | |
| 51 | - | ||
| 52 | } |
22 | } |
| 53 | 23 | ||
| 54 | uint8_t getTimingAdjust() { return timingAdjust; }; |
24 | uint8_t getTimingAdjust() { return timingAdjust; }; |
| 55 | 25 | ||
| 56 | void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; } |
26 | void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; } |
| 57 | 27 | ||
| 58 | int16_t getRpmMap(unsigned int i) |
28 | int16_t getRpmMap(unsigned int i) |
| 59 | { |
29 | { |
| 60 | if (i >= 0 && i < MAX_RPM_POINTS) |
30 | if (i >= 0 && i < MAX_RPM_POINTS) |
| 61 | return rpmMap[i]; |
31 | return timingMap.rpmMap[i]; |
| 62 | else |
32 | else |
| 63 | return 0; |
33 | return 0; |
| 64 | } |
34 | } |
| 65 | 35 | ||
| - | 36 | ||
| - | 37 | void setBaseMap(timingTable_t * map) |
|
| - | 38 | { |
|
| - | 39 | timingMap = *map; |
|
| - | 40 | } |
|
| - | 41 | ||
| - | 42 | ||
| - | 43 | ||
| 66 | void setRpmMap(unsigned int i, uint16_t val) |
44 | void setRpmMap(unsigned int i, uint16_t val) |
| 67 | { |
45 | { |
| 68 | #if WRITABLE_TABLE |
46 | #if WRITABLE_TABLE |
| 69 | if (i >= 0 && i < MAX_RPM_POINTS) |
47 | if (i >= 0 && i < MAX_RPM_POINTS) |
| 70 | rpmMap[i] = val; |
48 | timingMap.rpmMap[i] = val; |
| 71 | #endif |
49 | #endif |
| 72 | } |
50 | } |
| 73 | 51 | ||
| 74 | uint16_t getVacuumMap(unsigned int i) |
52 | uint16_t getVacuumMap(unsigned int i) |
| 75 | { |
53 | { |
| 76 | if (i >= 0 && i < MAX_VACUUM_POINTS) |
54 | if (i >= 0 && i < MAX_VACUUM_POINTS) |
| 77 | return vacuumMap[i]; |
55 | return timingMap.vacuumMap[i]; |
| 78 | else |
56 | else |
| 79 | return 0; |
57 | return 0; |
| 80 | } |
58 | } |
| 81 | 59 | ||
| 82 | void setVacuumMap(unsigned int i, uint16_t val) |
60 | void setVacuumMap(unsigned int i, uint16_t val) |
| 83 | { |
61 | { |
| 84 | #if WRITABLE_TABLE |
62 | #if WRITABLE_TABLE |
| 85 | if (i >= 0 && i < MAX_VACUUM_POINTS) |
63 | if (i >= 0 && i < MAX_VACUUM_POINTS) |
| 86 | vacuumMap[i] = val; |
64 | timingMap.vacuumMap[i] = val; |
| 87 | #endif |
65 | #endif |
| 88 | } |
66 | } |
| 89 | 67 | ||
| 90 | void setTiming(unsigned int vacuumIndex, unsigned int rpmIndex, uint8_t value) |
68 | void setTiming(unsigned int vacuumIndex, unsigned int rpmIndex, uint8_t value) |
| 91 | { |
69 | { |
| Line 93... | Line 71... | ||
| 93 | #if WRITABLE_TABLE |
71 | #if WRITABLE_TABLE |
| 94 | if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS) |
72 | if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS) |
| 95 | return; |
73 | return; |
| 96 | if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS) |
74 | if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS) |
| 97 | return; |
75 | return; |
| 98 | mapping[vacuumIndex][rpmIndex] = value; |
76 | timingMap.mapping[vacuumIndex][rpmIndex] = value; |
| 99 | #endif |
77 | #endif |
| 100 | } |
78 | } |
| 101 | 79 | ||
| 102 | uint8_t getTiming(unsigned int vacuumIndex, unsigned int rpmIndex) |
80 | uint8_t getTiming(unsigned int vacuumIndex, unsigned int rpmIndex) |
| 103 | { |
81 | { |
| 104 | if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS) |
82 | if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS) |
| 105 | return 0; |
83 | return 0; |
| 106 | if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS) |
84 | if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS) |
| 107 | return 0; |
85 | return 0; |
| 108 | return mapping[vacuumIndex][rpmIndex]; |
86 | return timingMap.mapping[vacuumIndex][rpmIndex]; |
| 109 | } |
87 | } |
| 110 | 88 | ||
| 111 | /// @brief Lookup a point in a 1 dimensional array - |
89 | /// @brief Lookup a point in a 1 dimensional array - |
| 112 | /// @param point Value to lookup |
90 | /// @param point Value to lookup |
| 113 | /// @param curve Lookup table |
91 | /// @param curve Lookup table |
| Line 165... | Line 143... | ||
| 165 | int mapTiming(int rpm, int vacuumMb) |
143 | int mapTiming(int rpm, int vacuumMb) |
| 166 | { |
144 | { |
| 167 | int angle = 0; |
145 | int angle = 0; |
| 168 | /* lookup the interpolated RPM point */ |
146 | /* lookup the interpolated RPM point */ |
| 169 | int16_t rpm_frac = 0; |
147 | int16_t rpm_frac = 0; |
| 170 | int rpm_index = lookup(rpm, rpmMap, MAX_RPM_POINTS, &rpm_frac); |
148 | int rpm_index = lookup(rpm, timingMap.rpmMap, MAX_RPM_POINTS, &rpm_frac); |
| 171 | if (rpm_index == NO_DATA) |
149 | if (rpm_index == NO_DATA) |
| 172 | return timingAdjust + MIN_ADVANCE; |
150 | return timingAdjust + MIN_ADVANCE; |
| 173 | 151 | ||
| 174 | /* lookup the interpolated vacuum point */ |
152 | /* lookup the interpolated vacuum point */ |
| 175 | int16_t vacuum_frac = 0; |
153 | int16_t vacuum_frac = 0; |
| 176 | int vacuum_index = lookup(vacuumMb, vacuumMap, MAX_VACUUM_POINTS, &vacuum_frac); |
154 | int vacuum_index = lookup(vacuumMb, timingMap.vacuumMap, MAX_VACUUM_POINTS, &vacuum_frac); |
| 177 | /* if there is a problem, bail out */ |
155 | /* if there is a problem, bail out */ |
| 178 | if (vacuum_index == NO_DATA) |
156 | if (vacuum_index == NO_DATA) |
| 179 | return timingAdjust + MIN_ADVANCE; |
157 | return timingAdjust + MIN_ADVANCE; |
| 180 | 158 | ||
| 181 | /* perform a bilinear mapping */ |
159 | /* perform a bilinear mapping */ |
| 182 | int top_advance; |
160 | int top_advance; |
| 183 | // we now have a position between two points in X and Y |
161 | // we now have a position between two points in X and Y |
| 184 | if (rpm_frac == 0) |
162 | if (rpm_frac == 0) |
| 185 | top_advance = mapping[vacuum_index][rpm_index] * INTERP_SCALE; |
163 | top_advance = timingMap.mapping[vacuum_index][rpm_index] * INTERP_SCALE; |
| 186 | // if fractional part then interpolate points off the map |
164 | // if fractional part then interpolate points off the map |
| 187 | else |
165 | else |
| 188 | top_advance = mapping[vacuum_index][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index][rpm_index + 1] * rpm_frac; |
166 | top_advance = timingMap.mapping[vacuum_index][rpm_index] * (INTERP_SCALE - rpm_frac) + |
| - | 167 | timingMap.mapping[vacuum_index][rpm_index + 1] * rpm_frac; |
|
| 189 | 168 | ||
| 190 | int bottom_advance; |
169 | int bottom_advance; |
| 191 | // if no fractional part, then the top and bottom advance point is the same |
170 | // if no fractional part, then the top and bottom advance point is the same |
| 192 | if (vacuum_frac == 0) |
171 | if (vacuum_frac == 0) |
| 193 | { |
172 | { |
| 194 | angle = top_advance * TimingScale / INTERP_SCALE; |
173 | angle = top_advance * TIMING_SCALE / INTERP_SCALE; |
| 195 | } |
174 | } |
| 196 | else |
175 | else |
| 197 | { |
176 | { |
| 198 | bottom_advance = mapping[vacuum_index + 1][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index + 1][rpm_index + 1] * rpm_frac; |
177 | bottom_advance = timingMap.mapping[vacuum_index + 1][rpm_index] * (INTERP_SCALE - rpm_frac) + |
| - | 178 | timingMap.mapping[vacuum_index + 1][rpm_index + 1] * rpm_frac; |
|
| 199 | /* interpolate down Y axis this time */ |
179 | /* interpolate down Y axis this time */ |
| 200 | int advance = top_advance * (INTERP_SCALE - vacuum_frac) + bottom_advance * vacuum_frac; |
180 | int advance = top_advance * (INTERP_SCALE - vacuum_frac) + bottom_advance * vacuum_frac; |
| 201 | /* point is scaled by two multiplications */ |
181 | /* point is scaled by two multiplications */ |
| 202 | angle = advance * TimingScale / (INTERP_SCALE * INTERP_SCALE); |
182 | angle = advance * TIMING_SCALE / (INTERP_SCALE * INTERP_SCALE); |
| 203 | } |
183 | } |
| 204 | 184 | ||
| 205 | if (angle < MIN_ADVANCE) |
185 | if (angle < MIN_ADVANCE) |
| 206 | angle = MIN_ADVANCE; |
186 | angle = MIN_ADVANCE; |
| 207 | if (angle > MAX_ADVANCE) |
187 | if (angle > MAX_ADVANCE) |