Subversion Repositories libIgnTiming

Rev

Rev 5 | Rev 7 | 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"
4
 
5
namespace
6
{
7
 
8
    unsigned constexpr INTERP_SCALE = 256;
9
 
4 mjames 10
    int constexpr TimingScale = TIMING_SCALE;
5 mjames 11
    int16_t constexpr NO_DATA = -1;
2 mjames 12
 
6 mjames 13
    int8_t timingAdjust = 0; // in 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] = {
2 mjames 17
        /* Table in degrees. */
18
        /* row for 0mb = centrifugal only */
6 mjames 19
        {12, 7, 7, 19, 25, 29, 29, 22},
2 mjames 20
        /* row for 166 mB*/
6 mjames 21
        {12, 7, 7, 21, 27, 31, 31, 24},
2 mjames 22
        /*   row for 225 mB */
6 mjames 23
        {12, 7, 7, 25, 31, 35, 35, 28},
2 mjames 24
        /* row for 300 mB*/
6 mjames 25
        {12, 7, 7, 29, 35, 39, 39, 33},
2 mjames 26
        /* row for 700 mB*/
6 mjames 27
        {12, 7, 7, 29, 35, 39, 39, 33},
2 mjames 28
        /* unused */
6 mjames 29
        {0, 0, 0, 0, 0, 0, 0, 0},
2 mjames 30
        /* unused */
6 mjames 31
        {0, 0, 0, 0, 0, 0, 0, 0},
2 mjames 32
        /* unused */
6 mjames 33
        {0, 0, 0, 0, 0, 0, 0, 0},
5 mjames 34
        /* unused */
6 mjames 35
 
5 mjames 36
    };
2 mjames 37
 
5 mjames 38
}
2 mjames 39
 
6 mjames 40
uint8_t getTimingAdjust() { return timingAdjust; };
41
 
42
void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; }
43
 
44
int16_t getRpmMap(int i)
2 mjames 45
{
6 mjames 46
    if (i >= 0 && i < MAX_TIMING_POINTS)
47
        return rpmMap[i];
48
    else
49
        return 0;
50
}
51
 
52
void setRpmMap(int i, int16_t val)
53
{
54
    if (i >= 0 && i < MAX_TIMING_POINTS)
55
        rpmMap[i] = val;
56
}
57
 
58
int16_t getVacuumMap(int i)
59
{
60
    if (i >= 0 && i < MAX_VACUUM_POINTS)
61
        return vacuumMap[i];
62
    else
63
        return 0;
64
}
65
 
66
void setVacuumMap(int i, int16_t val)
67
{
68
    if (i >= 0 && i < MAX_VACUUM_POINTS)
69
        vacuumMap[i] = val;
70
}
71
 
72
void setTiming(int vacuumIndex, int rpmIndex, uint8_t value)
73
{
74
    if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
75
        return;
76
    if (rpmIndex < 0 && rpmIndex >= MAX_VACUUM_POINTS)
77
        return;
78
    mapping[vacuumIndex][rpmIndex] = value;
79
}
80
 
81
uint8_t getTiming(int vacuumIndex, int rpmIndex)
82
{
83
    if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
84
        return 0;
85
    if (rpmIndex < 0 && rpmIndex >= MAX_VACUUM_POINTS)
86
        return 0;
87
    return mapping[vacuumIndex][rpmIndex];
88
}
89
 
90
int lookup(int point, int16_t const curve[], int size, int16_t *frac)
91
{
2 mjames 92
    // check lower bounds
93
    if (point < curve[0])
94
    {
95
        *frac = 0;
96
        return 0;
97
    }
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
 
104
    if (point >= curve[upper])
105
    {
106
        frac = 0;
107
        return upper;
108
    }
109
    for (int pt = 1; pt <= upper; pt++)
110
    {
111
        if ((point >= curve[pt - 1]) && (point < curve[pt]))
112
        {
113
            // how far along axis ?
114
            int offset = point - curve[pt - 1];
115
 
116
            int range1 = curve[pt] - curve[pt - 1];
117
 
118
            int range2 = INTERP_SCALE;
119
 
120
            *frac = ((offset * range2) / range1);
121
            return pt - 1;
122
        }
123
    }
124
    *frac = 0;
125
    return -1; // give up.
126
};
127
 
128
extern "C"
129
{
130
 
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;
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
 
151
        int bottom_advance;
152
        // if no fractional part, then the top and bottom advance point is the same
153
        if (vacuum_frac == 0)
154
        {
5 mjames 155
            angle = top_advance * TimingScale / INTERP_SCALE;
2 mjames 156
        }
157
        else
158
        {
159
            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 */
161
            int advance = top_advance * (INTERP_SCALE - vacuum_frac) + bottom_advance * vacuum_frac;
162
            /* point is scaled by two multiplications */
163
            angle = advance * TimingScale / (INTERP_SCALE * INTERP_SCALE);
164
        }
165
 
5 mjames 166
        assert((angle >= TimingScale * 7) && (angle < TimingScale * 50));
167
        return angle + timingAdjust;
2 mjames 168
    }
169
}