Subversion Repositories libIgnTiming

Rev

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