Subversion Repositories libIgnTiming

Rev

Rev 5 | Rev 7 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include <cstdint>
  2. #include <assert.h>
  3. #include "libIgnTiming/timing.h"
  4.  
  5. namespace
  6. {
  7.  
  8.     unsigned constexpr INTERP_SCALE = 256;
  9.  
  10.     int constexpr TimingScale = TIMING_SCALE;
  11.     int16_t constexpr NO_DATA = -1;
  12.  
  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] = {
  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},
  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.  
  36.     };
  37.  
  38. }
  39.  
  40. uint8_t getTimingAdjust() { return timingAdjust; };
  41.  
  42. void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; }
  43.  
  44. int16_t getRpmMap(int i)
  45. {
  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. {
  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.         {
  155.             angle = top_advance * TimingScale / INTERP_SCALE;
  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.  
  166.         assert((angle >= TimingScale * 7) && (angle < TimingScale * 50));
  167.         return angle + timingAdjust;
  168.     }
  169. }
  170.