Rev 8 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | mjames | 1 | #include <cstdint> |
2 | #include <assert.h> |
||
3 | #include "libIgnTiming/timing.h" |
||
11 | mjames | 4 | |
5 | #if !defined WRITABLE_TABLE |
||
6 | #define CONST_ATTR constexpr |
||
7 | #endif |
||
8 | |||
7 | mjames | 9 | #if defined __cplusplus |
10 | extern "C" |
||
2 | mjames | 11 | { |
7 | mjames | 12 | #endif |
2 | mjames | 13 | |
7 | mjames | 14 | namespace |
15 | { |
||
11 | mjames | 16 | int8_t timingAdjust = 0 * TIMING_SCALE; // in TIMING_SCALE |
2 | mjames | 17 | |
7 | mjames | 18 | unsigned constexpr INTERP_SCALE = 256; |
2 | mjames | 19 | |
7 | mjames | 20 | int constexpr TimingScale = TIMING_SCALE; |
21 | int16_t constexpr NO_DATA = -1; |
||
6 | mjames | 22 | |
11 | mjames | 23 | int16_t constexpr MAX_ADVANCE = 50 * TIMING_SCALE; |
24 | int16_t constexpr MIN_ADVANCE = 7 * TIMING_SCALE; |
||
2 | mjames | 25 | |
7 | mjames | 26 | // array of column headings |
11 | mjames | 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] = { |
||
7 | mjames | 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*/ |
||
11 | mjames | 41 | {12, 7, 7, 19, 25, 29, 29, 22}, |
7 | mjames | 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 */ |
||
2 | mjames | 49 | |
7 | mjames | 50 | }; |
6 | mjames | 51 | |
7 | mjames | 52 | } |
6 | mjames | 53 | |
7 | mjames | 54 | uint8_t getTimingAdjust() { return timingAdjust; }; |
6 | mjames | 55 | |
7 | mjames | 56 | void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; } |
6 | mjames | 57 | |
7 | mjames | 58 | int16_t getRpmMap(unsigned int i) |
59 | { |
||
60 | if (i >= 0 && i < MAX_RPM_POINTS) |
||
61 | return rpmMap[i]; |
||
62 | else |
||
63 | return 0; |
||
64 | } |
||
6 | mjames | 65 | |
7 | mjames | 66 | void setRpmMap(unsigned int i, uint16_t val) |
67 | { |
||
11 | mjames | 68 | #if WRITABLE_TABLE |
7 | mjames | 69 | if (i >= 0 && i < MAX_RPM_POINTS) |
70 | rpmMap[i] = val; |
||
11 | mjames | 71 | #endif |
7 | mjames | 72 | } |
6 | mjames | 73 | |
7 | mjames | 74 | uint16_t getVacuumMap(unsigned int i) |
75 | { |
||
76 | if (i >= 0 && i < MAX_VACUUM_POINTS) |
||
77 | return vacuumMap[i]; |
||
78 | else |
||
79 | return 0; |
||
80 | } |
||
6 | mjames | 81 | |
7 | mjames | 82 | void setVacuumMap(unsigned int i, uint16_t val) |
83 | { |
||
11 | mjames | 84 | #if WRITABLE_TABLE |
7 | mjames | 85 | if (i >= 0 && i < MAX_VACUUM_POINTS) |
86 | vacuumMap[i] = val; |
||
11 | mjames | 87 | #endif |
7 | mjames | 88 | } |
6 | mjames | 89 | |
7 | mjames | 90 | void setTiming(unsigned int vacuumIndex, unsigned int rpmIndex, uint8_t value) |
2 | mjames | 91 | { |
11 | mjames | 92 | |
93 | #if WRITABLE_TABLE |
||
7 | mjames | 94 | if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS) |
95 | return; |
||
96 | if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS) |
||
97 | return; |
||
98 | mapping[vacuumIndex][rpmIndex] = value; |
||
11 | mjames | 99 | #endif |
2 | mjames | 100 | } |
101 | |||
7 | mjames | 102 | uint8_t getTiming(unsigned int vacuumIndex, unsigned int rpmIndex) |
2 | mjames | 103 | { |
7 | mjames | 104 | if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS) |
105 | return 0; |
||
106 | if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS) |
||
107 | return 0; |
||
108 | return mapping[vacuumIndex][rpmIndex]; |
||
2 | mjames | 109 | } |
7 | mjames | 110 | |
11 | mjames | 111 | /// @brief Lookup a point in a 1 dimensional array - |
112 | /// @param point Value to lookup |
||
113 | /// @param curve Lookup table |
||
114 | /// @param size Size of lookup table |
||
115 | /// @param [out] frac fraction of distance from first point in array |
||
116 | /// @return index in array or NO_DATA if operations fail |
||
7 | mjames | 117 | int lookup(int point, int16_t const curve[], int size, int16_t *frac) |
2 | mjames | 118 | { |
7 | mjames | 119 | // check lower bounds |
120 | if (point < curve[0]) |
||
2 | mjames | 121 | { |
7 | mjames | 122 | *frac = 0; |
123 | return 0; |
||
124 | } |
||
125 | // check upper bounds |
||
126 | // find the upper boundary by looking for non -1 points |
||
127 | int upper = size - 1; |
||
8 | mjames | 128 | while (upper != 0 && curve[upper] == NO_DATA) |
7 | mjames | 129 | upper--; |
2 | mjames | 130 | |
7 | mjames | 131 | if (point >= curve[upper]) |
132 | { |
||
133 | *frac = 0; |
||
134 | return upper; |
||
135 | } |
||
136 | for (int pt = 1; pt <= upper; pt++) |
||
137 | { |
||
138 | if ((point >= curve[pt - 1]) && (point < curve[pt])) |
||
139 | { |
||
2 | mjames | 140 | |
7 | mjames | 141 | int range1 = curve[pt] - curve[pt - 1]; |
2 | mjames | 142 | |
7 | mjames | 143 | if (range1 == 0) |
144 | { |
||
145 | *frac = 0; |
||
146 | return pt - 1; |
||
147 | } |
||
148 | |||
149 | // how far along axis ? |
||
150 | int offset = point - curve[pt - 1]; |
||
151 | |||
152 | int range2 = INTERP_SCALE; |
||
153 | |||
154 | *frac = ((offset * range2) / range1); |
||
155 | return pt - 1; |
||
156 | } |
||
2 | mjames | 157 | } |
7 | mjames | 158 | *frac = 0; |
11 | mjames | 159 | return NO_DATA; // give up. |
7 | mjames | 160 | }; |
2 | mjames | 161 | |
7 | mjames | 162 | extern "C" |
2 | mjames | 163 | { |
164 | |||
7 | mjames | 165 | int mapTiming(int rpm, int vacuumMb) |
166 | { |
||
167 | int angle = 0; |
||
168 | /* lookup the interpolated RPM point */ |
||
169 | int16_t rpm_frac = 0; |
||
170 | int rpm_index = lookup(rpm, rpmMap, MAX_RPM_POINTS, &rpm_frac); |
||
171 | if (rpm_index == NO_DATA) |
||
172 | return timingAdjust + MIN_ADVANCE; |
||
2 | mjames | 173 | |
7 | mjames | 174 | /* lookup the interpolated vacuum point */ |
175 | int16_t vacuum_frac = 0; |
||
176 | int vacuum_index = lookup(vacuumMb, vacuumMap, MAX_VACUUM_POINTS, &vacuum_frac); |
||
177 | /* if there is a problem, bail out */ |
||
178 | if (vacuum_index == NO_DATA) |
||
179 | return timingAdjust + MIN_ADVANCE; |
||
2 | mjames | 180 | |
7 | mjames | 181 | /* perform a bilinear mapping */ |
182 | int top_advance; |
||
183 | // we now have a position between two points in X and Y |
||
184 | if (rpm_frac == 0) |
||
185 | top_advance = mapping[vacuum_index][rpm_index] * INTERP_SCALE; |
||
186 | // if fractional part then interpolate points off the map |
||
187 | else |
||
188 | top_advance = mapping[vacuum_index][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index][rpm_index + 1] * rpm_frac; |
||
189 | |||
190 | int bottom_advance; |
||
191 | // if no fractional part, then the top and bottom advance point is the same |
||
192 | if (vacuum_frac == 0) |
||
193 | { |
||
194 | angle = top_advance * TimingScale / INTERP_SCALE; |
||
195 | } |
||
196 | else |
||
197 | { |
||
198 | bottom_advance = mapping[vacuum_index + 1][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index + 1][rpm_index + 1] * rpm_frac; |
||
199 | /* interpolate down Y axis this time */ |
||
200 | int advance = top_advance * (INTERP_SCALE - vacuum_frac) + bottom_advance * vacuum_frac; |
||
201 | /* point is scaled by two multiplications */ |
||
202 | angle = advance * TimingScale / (INTERP_SCALE * INTERP_SCALE); |
||
203 | } |
||
204 | |||
205 | if (angle < MIN_ADVANCE) |
||
206 | angle = MIN_ADVANCE; |
||
207 | if (angle > MAX_ADVANCE) |
||
208 | angle = MAX_ADVANCE; |
||
209 | |||
210 | return angle + timingAdjust; |
||
2 | mjames | 211 | } |
212 | } |
||
7 | mjames | 213 | #if defined __cplusplus |
2 | mjames | 214 | } |
7 | mjames | 215 | #endif |