Subversion Repositories libIgnTiming

Rev

Rev 11 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include <cstdint>
  2. #include <assert.h>
  3. #include "libIgnTiming/timing.h"
  4. #include "libIgnTiming/basemap.h"
  5.  
  6.  
  7. #if defined __cplusplus
  8. extern "C"
  9. {
  10. #endif
  11.  
  12.     namespace
  13.     {
  14.         int8_t timingAdjust = 0 * TIMING_SCALE; // in TIMING_SCALE
  15.         // local copy of the data structure
  16.         timingTable_t timingMap = baseTimingMap;
  17.  
  18.         int16_t constexpr MAX_ADVANCE = 50 * TIMING_SCALE;
  19.         int16_t constexpr MIN_ADVANCE = 7 * TIMING_SCALE;
  20.  
  21.  
  22.     }
  23.  
  24.     uint8_t getTimingAdjust() { return timingAdjust; };
  25.  
  26.     void setTimingAdjust(int8_t adjust) { timingAdjust = adjust; }
  27.  
  28.     int16_t getRpmMap(unsigned int i)
  29.     {
  30.         if (i >= 0 && i < MAX_RPM_POINTS)
  31.             return timingMap.rpmMap[i];
  32.         else
  33.             return 0;
  34.     }
  35.  
  36.  
  37.     void setBaseMap(timingTable_t * map)
  38.     {
  39.         timingMap = *map;
  40.     }
  41.  
  42.  
  43.  
  44.     void setRpmMap(unsigned int i, uint16_t val)
  45.     {
  46. #if WRITABLE_TABLE
  47.         if (i >= 0 && i < MAX_RPM_POINTS)
  48.             timingMap.rpmMap[i] = val;
  49. #endif
  50.     }
  51.  
  52.     uint16_t getVacuumMap(unsigned int i)
  53.     {
  54.         if (i >= 0 && i < MAX_VACUUM_POINTS)
  55.             return timingMap.vacuumMap[i];
  56.         else
  57.             return 0;
  58.     }
  59.  
  60.     void setVacuumMap(unsigned int i, uint16_t val)
  61.     {
  62. #if WRITABLE_TABLE
  63.         if (i >= 0 && i < MAX_VACUUM_POINTS)
  64.             timingMap.vacuumMap[i] = val;
  65. #endif
  66.     }
  67.  
  68.     void setTiming(unsigned int vacuumIndex, unsigned int rpmIndex, uint8_t value)
  69.     {
  70.  
  71. #if WRITABLE_TABLE
  72.         if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
  73.             return;
  74.         if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS)
  75.             return;
  76.         timingMap.mapping[vacuumIndex][rpmIndex] = value;
  77. #endif
  78.     }
  79.  
  80.     uint8_t getTiming(unsigned int vacuumIndex, unsigned int rpmIndex)
  81.     {
  82.         if (vacuumIndex < 0 && vacuumIndex >= MAX_VACUUM_POINTS)
  83.             return 0;
  84.         if (rpmIndex < 0 && rpmIndex >= MAX_RPM_POINTS)
  85.             return 0;
  86.         return timingMap.mapping[vacuumIndex][rpmIndex];
  87.     }
  88.  
  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
  95.     int lookup(int point, int16_t const curve[], int size, int16_t *frac)
  96.     {
  97.         // check lower bounds
  98.         if (point < curve[0])
  99.         {
  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;
  106.         while (upper != 0 && curve[upper] == NO_DATA)
  107.             upper--;
  108.  
  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.             {
  118.  
  119.                 int range1 = curve[pt] - curve[pt - 1];
  120.  
  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.             }
  135.         }
  136.         *frac = 0;
  137.         return NO_DATA; // give up.
  138.     };
  139.  
  140.     extern "C"
  141.     {
  142.  
  143.         int mapTiming(int rpm, int vacuumMb)
  144.         {
  145.             int angle = 0;
  146.             /* lookup the interpolated RPM point */
  147.             int16_t rpm_frac = 0;
  148.             int rpm_index = lookup(rpm, timingMap.rpmMap, MAX_RPM_POINTS, &rpm_frac);
  149.             if (rpm_index == NO_DATA)
  150.                 return timingAdjust + MIN_ADVANCE;
  151.  
  152.             /* lookup the interpolated vacuum point */
  153.             int16_t vacuum_frac = 0;
  154.             int vacuum_index = lookup(vacuumMb, timingMap.vacuumMap, MAX_VACUUM_POINTS, &vacuum_frac);
  155.             /* if there is a problem, bail out */
  156.             if (vacuum_index == NO_DATA)
  157.                 return timingAdjust + MIN_ADVANCE;
  158.  
  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)
  163.                 top_advance = timingMap.mapping[vacuum_index][rpm_index] * INTERP_SCALE;
  164.             // if fractional part then interpolate points off the map
  165.             else
  166.                 top_advance = timingMap.mapping[vacuum_index][rpm_index] * (INTERP_SCALE - rpm_frac) +
  167.                               timingMap.mapping[vacuum_index][rpm_index + 1] * rpm_frac;
  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.             {
  173.                 angle = top_advance * TIMING_SCALE / INTERP_SCALE;
  174.             }
  175.             else
  176.             {
  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;
  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 */
  182.                 angle = advance * TIMING_SCALE / (INTERP_SCALE * INTERP_SCALE);
  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;
  191.         }
  192.     }
  193. #if defined __cplusplus
  194. }
  195. #endif
  196.