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) |