Subversion Repositories libIgnTiming

Rev

Rev 8 | 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. #if !defined WRITABLE_TABLE
  6. #define CONST_ATTR constexpr
  7. #endif
  8.  
  9. #if defined __cplusplus
  10. extern "C"
  11. {
  12. #endif
  13.  
  14.     namespace
  15.     {
  16.         int8_t timingAdjust = 0 * TIMING_SCALE; // in TIMING_SCALE
  17.  
  18.         unsigned constexpr INTERP_SCALE = 256;
  19.  
  20.         int constexpr TimingScale = TIMING_SCALE;
  21.         int16_t constexpr NO_DATA = -1;
  22.  
  23.         int16_t constexpr MAX_ADVANCE = 50 * TIMING_SCALE;
  24.         int16_t constexpr MIN_ADVANCE = 7 * TIMING_SCALE;
  25.  
  26.         // array of column headings
  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] = {
  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*/
  41.             {12, 7, 7, 19, 25, 29, 29, 22},
  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 */
  49.  
  50.         };
  51.  
  52.     }
  53.  
  54.     uint8_t getTimingAdjust() { return timingAdjust; };
  55.  
  56.     void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; }
  57.  
  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.     }
  65.  
  66.     void setRpmMap(unsigned int i, uint16_t val)
  67.     {
  68. #if WRITABLE_TABLE
  69.         if (i >= 0 && i < MAX_RPM_POINTS)
  70.             rpmMap[i] = val;
  71. #endif
  72.     }
  73.  
  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.     }
  81.  
  82.     void setVacuumMap(unsigned int i, uint16_t val)
  83.     {
  84. #if WRITABLE_TABLE
  85.         if (i >= 0 && i < MAX_VACUUM_POINTS)
  86.             vacuumMap[i] = val;
  87. #endif
  88.     }
  89.  
  90.     void setTiming(unsigned int vacuumIndex, unsigned int rpmIndex, uint8_t value)
  91.     {
  92.  
  93. #if WRITABLE_TABLE
  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;
  99. #endif
  100.     }
  101.  
  102.     uint8_t getTiming(unsigned int vacuumIndex, unsigned int rpmIndex)
  103.     {
  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];
  109.     }
  110.  
  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
  117.     int lookup(int point, int16_t const curve[], int size, int16_t *frac)
  118.     {
  119.         // check lower bounds
  120.         if (point < curve[0])
  121.         {
  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;
  128.         while (upper != 0 && curve[upper] == NO_DATA)
  129.             upper--;
  130.  
  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.             {
  140.  
  141.                 int range1 = curve[pt] - curve[pt - 1];
  142.  
  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.             }
  157.         }
  158.         *frac = 0;
  159.         return NO_DATA; // give up.
  160.     };
  161.  
  162.     extern "C"
  163.     {
  164.  
  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;
  173.  
  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;
  180.  
  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;
  211.         }
  212.     }
  213. #if defined __cplusplus
  214. }
  215. #endif
  216.