Subversion Repositories libIgnTiming

Rev

Rev 6 | Rev 8 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6 Rev 7
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
 
-
 
-
 
4
#if defined __cplusplus
5
namespace
5
extern "C"
6
{
6
{
-
 
7
#endif
7
 
8
 
8
    unsigned constexpr INTERP_SCALE = 256;
9
    namespace
-
 
10
    {
9
 
11
 
10
    int constexpr TimingScale = TIMING_SCALE;
-
 
11
    int16_t constexpr NO_DATA = -1;
12
        unsigned constexpr INTERP_SCALE = 256;
12
 
13
 
13
    int8_t timingAdjust = 0; // in TIMING_SCALE
14
        int constexpr TimingScale = TIMING_SCALE;
14
    int16_t rpmMap[MAX_TIMING_POINTS] = {400, 750, 1000, 1500, 2500, 3500, 4500, 6000};
-
 
15
    int16_t vacuumMap[MAX_VACUUM_POINTS] = {0, 166, 225, 300, 700, NO_DATA, NO_DATA, NO_DATA};
-
 
16
    uint8_t mapping[MAX_VACUUM_POINTS][MAX_TIMING_POINTS] = {
-
 
17
        /* Table in degrees. */
-
 
18
        /* row for 0mb = centrifugal only */
-
 
19
        {12, 7, 7, 19, 25, 29, 29, 22},
-
 
20
        /* row for 166 mB*/
-
 
21
        {12, 7, 7, 21, 27, 31, 31, 24},
-
 
22
        /*   row for 225 mB */
-
 
23
        {12, 7, 7, 25, 31, 35, 35, 28},
-
 
24
        /* row for 300 mB*/
-
 
25
        {12, 7, 7, 29, 35, 39, 39, 33},
-
 
26
        /* row for 700 mB*/
-
 
27
        {12, 7, 7, 29, 35, 39, 39, 33},
15
        int16_t constexpr NO_DATA = -1;
28
        /* unused */
-
 
29
        {0, 0, 0, 0, 0, 0, 0, 0},
-
 
30
        /* unused */
-
 
31
        {0, 0, 0, 0, 0, 0, 0, 0},
-
 
32
        /* unused */
-
 
33
        {0, 0, 0, 0, 0, 0, 0, 0},
-
 
34
        /* unused */
-
 
35
 
16
 
-
 
17
        int16_t MAX_ADVANCE = 50 * TIMING_SCALE;
36
    };
18
        int16_t MIN_ADVANCE = 7 * TIMING_SCALE;
37
 
19
 
-
 
20
        int8_t timingAdjust = 0; // in TIMING_SCALE
-
 
21
        // array of column headings
-
 
22
        int16_t rpmMap[MAX_RPM_POINTS] = {400, 750, 1000, 1500, 2500, 3500, 4500, 6000};
-
 
23
        // column of row values - in 1000-pressure 
-
 
24
        int16_t vacuumMap[MAX_VACUUM_POINTS] = {0, 166, 225, 300, 700, 1000, NO_DATA, NO_DATA};
-
 
25
        uint8_t mapping[MAX_VACUUM_POINTS][MAX_RPM_POINTS] = {
38
}
-
 
-
 
26
            /* Table in degrees. */
-
 
27
            /* row for 0mb = centrifugal only */
-
 
28
            {12, 7, 7, 19, 25, 29, 29, 22},
-
 
29
            /* row for 166 mB*/
-
 
30
            {12, 7, 7, 21, 27, 31, 31, 24},
-
 
31
            /*   row for 225 mB */
-
 
32
            {12, 7, 7, 25, 31, 35, 35, 28},
-
 
33
            /* row for 300 mB*/
-
 
34
            {12, 7, 7, 29, 35, 39, 39, 33},
-
 
35
            /* row for 700 mB*/
-
 
36
            {12, 7, 7, 29, 35, 39, 39, 33},
-
 
37
            /* row for 1000 mB - used when pressure drops off the scale */
-
 
38
            {7, 7, 7, 7, 7, 7, 7, 7},
-
 
39
            /* unused */
-
 
40
            {0, 0, 0, 0, 0, 0, 0, 0},
-
 
41
            /* unused */
-
 
42
            {0, 0, 0, 0, 0, 0, 0, 0},
-
 
43
            /* unused */
39
 
44
 
40
uint8_t getTimingAdjust() { return timingAdjust; };
45
        };
41
 
46
 
42
void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; }
-
 
-
 
47
    }
43
 
48
 
44
int16_t getRpmMap(int i)
-
 
45
{
-
 
46
    if (i >= 0 && i < MAX_TIMING_POINTS)
-
 
47
        return rpmMap[i];
49
    uint8_t getTimingAdjust() { return timingAdjust; };
48
    else
-
 
49
        return 0;
-
 
50
}
-
 
51
 
50
 
52
void setRpmMap(int i, int16_t val)
51
    void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; }
53
{
-
 
54
    if (i >= 0 && i < MAX_TIMING_POINTS)
-
 
55
        rpmMap[i] = val;
-
 
56
}
-
 
57
 
52
 
58
int16_t getVacuumMap(int i)
53
    int16_t getRpmMap(unsigned int i)
59
{
54
    {
60
    if (i >= 0 && i < MAX_VACUUM_POINTS)
55
        if (i >= 0 && i < MAX_RPM_POINTS)
61
        return vacuumMap[i];
56
            return rpmMap[i];
62
    else
57
        else
63
        return 0;
58
            return 0;
64
}
59
    }
65
 
60
 
66
void setVacuumMap(int i, int16_t val)
61
    void setRpmMap(unsigned int i, uint16_t val)
67
{
62
    {
68
    if (i >= 0 && i < MAX_VACUUM_POINTS)
63
        if (i >= 0 && i < MAX_RPM_POINTS)
69
        vacuumMap[i] = val;
64
            rpmMap[i] = val;
70
}
65
    }
71
 
66
 
72
void setTiming(int vacuumIndex, int rpmIndex, uint8_t value)
67
    uint16_t getVacuumMap(unsigned int i)
73
{
68
    {
74
    if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
69
        if (i >= 0 && i < MAX_VACUUM_POINTS)
75
        return;
70
            return vacuumMap[i];
76
    if (rpmIndex < 0 && rpmIndex >= MAX_VACUUM_POINTS)
-
 
77
        return;
71
        else
78
    mapping[vacuumIndex][rpmIndex] = value;
72
            return 0;
79
}
73
    }
80
 
74
 
81
uint8_t getTiming(int vacuumIndex, int rpmIndex)
75
    void setVacuumMap(unsigned int i, uint16_t val)
82
{
76
    {
83
    if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
-
 
84
        return 0;
-
 
85
    if (rpmIndex < 0 && rpmIndex >= MAX_VACUUM_POINTS)
77
        if (i >= 0 && i < MAX_VACUUM_POINTS)
86
        return 0;
-
 
87
    return mapping[vacuumIndex][rpmIndex];
78
            vacuumMap[i] = val;
88
}
79
    }
89
 
80
 
90
int lookup(int point, int16_t const curve[], int size, int16_t *frac)
81
    void setTiming(unsigned int vacuumIndex, unsigned int rpmIndex, uint8_t value)
91
{
-
 
92
    // check lower bounds
-
 
93
    if (point < curve[0])
-
 
94
    {
82
    {
-
 
83
        if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
95
        *frac = 0;
84
            return;
-
 
85
        if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS)
96
        return 0;
86
            return;
-
 
87
        mapping[vacuumIndex][rpmIndex] = value;
97
    }
88
    }
98
    // check upper bounds
-
 
99
    // find the upper boundary by looking for non -1 points
-
 
100
    int upper = size - 1;
-
 
101
    while (curve[upper] <= 0)
-
 
102
        upper--;
-
 
103
 
89
 
104
    if (point >= curve[upper])
90
    uint8_t getTiming(unsigned int vacuumIndex, unsigned int rpmIndex)
105
    {
91
    {
-
 
92
        if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
106
        frac = 0;
93
            return 0;
-
 
94
        if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS)
107
        return upper;
95
            return 0;
-
 
96
        return mapping[vacuumIndex][rpmIndex];
108
    }
97
    }
-
 
98
 
109
    for (int pt = 1; pt <= upper; pt++)
99
    int lookup(int point, int16_t const curve[], int size, int16_t *frac)
110
    {
100
    {
-
 
101
        // check lower bounds
111
        if ((point >= curve[pt - 1]) && (point < curve[pt]))
102
        if (point < curve[0])
112
        {
103
        {
113
            // how far along axis ?
104
            *frac = 0;
-
 
105
            return 0;
-
 
106
        }
-
 
107
        // check upper bounds
-
 
108
        // find the upper boundary by looking for non -1 points
114
            int offset = point - curve[pt - 1];
109
        int upper = size - 1;
-
 
110
        while (curve[upper] == NO_DATA)
-
 
111
            upper--;
115
 
112
 
-
 
113
        if (point >= curve[upper])
-
 
114
        {
-
 
115
            *frac = 0;
-
 
116
            return upper;
-
 
117
        }
-
 
118
        for (int pt = 1; pt <= upper; pt++)
-
 
119
        {
116
            int range1 = curve[pt] - curve[pt - 1];
120
            if ((point >= curve[pt - 1]) && (point < curve[pt]))
-
 
121
            {
117
 
122
 
118
            int range2 = INTERP_SCALE;
123
                int range1 = curve[pt] - curve[pt - 1];
119
 
124
 
120
            *frac = ((offset * range2) / range1);
125
                if (range1 == 0)
121
            return pt - 1;
126
                {
122
        }
127
                    *frac = 0;
123
    }
-
 
124
    *frac = 0;
128
                    return pt - 1;
125
    return -1; // give up.
129
                }
126
};
-
 
127
 
130
 
128
extern "C"
131
                // how far along axis ?
129
{
-
 
-
 
132
                int offset = point - curve[pt - 1];
130
 
133
 
131
    int mapTiming(int rpm, int vacuumMb)
-
 
132
    {
-
 
133
        int angle = 0;
-
 
134
        /* lookup the interpolated RPM point */
-
 
135
        int16_t rpm_frac = 0;
-
 
136
        int rpm_index = lookup(rpm, rpmMap, MAX_TIMING_POINTS, &rpm_frac);
-
 
137
 
-
 
138
        /* lookup the interpolated vacuum point */
-
 
139
        int16_t vacuum_frac = 0;
-
 
140
        int vacuum_index = lookup(vacuumMb, vacuumMap, MAX_VACUUM_POINTS, &vacuum_frac);
-
 
141
 
-
 
142
        /* perform a bilinear mapping */
-
 
143
        int top_advance;
-
 
144
        // we now have a position between two points in X and Y
-
 
145
        if (rpm_frac == 0)
-
 
146
            top_advance = mapping[vacuum_index][rpm_index] * INTERP_SCALE;
134
                int range2 = INTERP_SCALE;
147
        // if fractional part then interpolate points off the map
-
 
148
        else
-
 
149
            top_advance = mapping[vacuum_index][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index][rpm_index + 1] * rpm_frac;
-
 
150
 
135
 
151
        int bottom_advance;
-
 
152
        // if no fractional part, then the top and bottom advance point is the same
136
                *frac = ((offset * range2) / range1);
153
        if (vacuum_frac == 0)
137
                return pt - 1;
154
        {
138
            }
155
            angle = top_advance * TimingScale / INTERP_SCALE;
-
 
156
        }
139
        }
157
        else
140
        *frac = 0;
-
 
141
        return -1; // give up.
-
 
142
    };
-
 
143
 
-
 
144
    extern "C"
-
 
145
    {
-
 
146
 
-
 
147
        int mapTiming(int rpm, int vacuumMb)
158
        {
148
        {
-
 
149
            int angle = 0;
-
 
150
            /* lookup the interpolated RPM point */
-
 
151
            int16_t rpm_frac = 0;
-
 
152
            int rpm_index = lookup(rpm, rpmMap, MAX_RPM_POINTS, &rpm_frac);
-
 
153
            if (rpm_index == NO_DATA)
-
 
154
                return timingAdjust + MIN_ADVANCE;
-
 
155
 
-
 
156
            /* lookup the interpolated vacuum point */
-
 
157
            int16_t vacuum_frac = 0;
-
 
158
            int vacuum_index = lookup(vacuumMb, vacuumMap, MAX_VACUUM_POINTS, &vacuum_frac);
-
 
159
            /* if there is a problem, bail out */
-
 
160
            if (vacuum_index == NO_DATA)
-
 
161
                return timingAdjust + MIN_ADVANCE;
-
 
162
 
-
 
163
            /* perform a bilinear mapping */
-
 
164
            int top_advance;
-
 
165
            // we now have a position between two points in X and Y
-
 
166
            if (rpm_frac == 0)
-
 
167
                top_advance = mapping[vacuum_index][rpm_index] * INTERP_SCALE;
-
 
168
            // if fractional part then interpolate points off the map
-
 
169
            else
-
 
170
                top_advance = mapping[vacuum_index][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index][rpm_index + 1] * rpm_frac;
-
 
171
 
-
 
172
            int bottom_advance;
-
 
173
            // if no fractional part, then the top and bottom advance point is the same
-
 
174
            if (vacuum_frac == 0)
-
 
175
            {
-
 
176
                angle = top_advance * TimingScale / INTERP_SCALE;
-
 
177
            }
-
 
178
            else
-
 
179
            {
159
            bottom_advance = mapping[vacuum_index + 1][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index + 1][rpm_index + 1] * rpm_frac;
180
                bottom_advance = mapping[vacuum_index + 1][rpm_index] * (INTERP_SCALE - rpm_frac) + mapping[vacuum_index + 1][rpm_index + 1] * rpm_frac;
160
            /* interpolate down Y axis this time */
181
                /* interpolate down Y axis this time */
161
            int advance = top_advance * (INTERP_SCALE - vacuum_frac) + bottom_advance * vacuum_frac;
182
                int advance = top_advance * (INTERP_SCALE - vacuum_frac) + bottom_advance * vacuum_frac;
162
            /* point is scaled by two multiplications */
183
                /* point is scaled by two multiplications */
163
            angle = advance * TimingScale / (INTERP_SCALE * INTERP_SCALE);
184
                angle = advance * TimingScale / (INTERP_SCALE * INTERP_SCALE);
164
        }
185
            }
-
 
186
 
-
 
187
            if (angle < MIN_ADVANCE)
-
 
188
                angle = MIN_ADVANCE;
-
 
189
            if (angle > MAX_ADVANCE)
-
 
190
                angle = MAX_ADVANCE;
165
 
191
 
166
        assert((angle >= TimingScale * 7) && (angle < TimingScale * 50));
-
 
167
        return angle + timingAdjust;
192
            return angle + timingAdjust;
-
 
193
        }
168
    }
194
    }
-
 
195
#if defined __cplusplus
169
}
196
}
-
 
197
#endif