LCOV - code coverage report
Current view: top level - firmware/hw_layer/sensors - hip9011_logic.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 62 100 62.0 %
Date: 2024-04-25 02:23:43 Functions: 10 14 71.4 %

          Line data    Source code
       1             : /*
       2             :  * @file HIP9011_logic.cpp
       3             :  *
       4             :  *  Created on: Jan 3, 2019
       5             :  * @author Andrey Belomutskiy, (c) 2012-2020
       6             :  */
       7             : 
       8             : #include "pch.h"
       9             : 
      10             : /* getCylinderKnockBank */
      11             : #include "knock_logic.h"
      12             : #include "hip9011_logic.h"
      13             : 
      14             : /*==========================================================================*/
      15             : /* Local definitions.                                                                                                           */
      16             : /*==========================================================================*/
      17             : 
      18             : /*==========================================================================*/
      19             : /* Local variables and types.                                                                                           */
      20             : /*==========================================================================*/
      21             : 
      22             : /**
      23             :  * These are HIP9011 magic values - integrator time constants in uS
      24             :  */
      25             : const int integratorValues[INT_LOOKUP_SIZE] = {
      26             : /* 00 */ 40,  45,  50,  55,  60,  65,  70,  75,
      27             : /* 08 */ 80,  90, 100, 110, 120, 130, 140, 150,
      28             : /* 16 */160, 180, 200, 220, 240, 260, 280, 300,
      29             : /* 24 */320, 360, 400, 440, 480, 520, 560, 600
      30             : };
      31             : 
      32             : const float gainLookupInReverseOrder[GAIN_LOOKUP_SIZE] = {
      33             : /* 00 */0.111, 0.118, 0.125, 0.129, 0.133, 0.138, 0.143, 0.148,
      34             : /* 08 */0.154, 0.160, 0.167, 0.174, 0.182, 0.190, 0.200, 0.211,
      35             : /* 16 */0.222, 0.236, 0.250, 0.258, 0.267, 0.276, 0.286, 0.296,
      36             : /* 24 */0.308, 0.320, 0.333, 0.348, 0.364, 0.381, 0.400, 0.421,
      37             : /* 32 */0.444, 0.471, 0.500, 0.548, 0.567, 0.586, 0.607, 0.630,
      38             : /* 40 */0.654, 0.680, 0.708, 0.739, 0.773, 0.810, 0.850, 0.895,
      39             : /* 48 */0.944, 1.000, 1.063, 1.143, 1.185, 1.231, 1.280, 1.333,
      40             : /* 56 */1.391, 1.455, 1.523, 1.600, 1.684, 1.778, 1.882, 2.000
      41             : };
      42             : 
      43             : const float bandFreqLookup[BAND_LOOKUP_SIZE] = {
      44             : /* 00 */ 1.22,  1.26,  1.31,  1.35,  1.40,  1.45,  1.51,  1.57,
      45             : /* 08 */ 1.63,  1.71,  1.78,  1.87,  1.96,  2.07,  2.18,  2.31,
      46             : /* 16 */ 2.46,  2.54,  2.62,  2.71,  2.81,  2.92,  3.03,  3.15,
      47             : /* 24 */ 3.28,  3.43,  3.59,  3.76,  3.95,  4.16,  4.39,  4.66,
      48             : /* 32 */ 4.95,  5.12,  5.29,  5.48,  5.68,  5.90,  6.12,  6.37,
      49             : /* 40 */ 6.64,  6.94,  7.27,  7.63,  8.02,  8.46,  8.95,  9.50,
      50             : /* 48 */10.12, 10.46, 10.83, 11.22, 11.65, 12.10, 12.60, 13.14,
      51             : /* 56 */13.72, 14.36, 15.07, 15.84, 16.71, 17.67, 18.76, 19.98
      52             : };
      53             : 
      54             : /*==========================================================================*/
      55             : /* Forward declarations                                                                                                         */
      56             : /*==========================================================================*/
      57             : 
      58             : /*==========================================================================*/
      59             : /* Exported.                                                                                                                            */
      60             : /*==========================================================================*/
      61             : 
      62           4 : HIP9011::HIP9011(Hip9011HardwareInterface *hardware) {
      63           4 :         this->hw = hardware;
      64           4 : }
      65             : 
      66           4 : int HIP9011::sendCommand(uint8_t cmd) {
      67           4 :         return hw->sendSyncCommand(cmd, NULL);
      68             : }
      69             : 
      70           0 : int HIP9011::sendCommandGetReply(uint8_t cmd, uint8_t *reply) {
      71           0 :         return hw->sendSyncCommand(cmd, reply);
      72             : }
      73             : 
      74             : /**
      75             :  * @return frequency band we are interested in
      76             :  */
      77           5 : float HIP9011::getBand(DEFINE_HIP_PARAMS) {
      78           5 :         return GET_CONFIG_VALUE(knockBandCustom) == 0 ?
      79           4 :                         HIP9011_BAND(GET_CONFIG_VALUE(cylinderBore)) :
      80           5 :                         GET_CONFIG_VALUE(knockBandCustom);
      81             : }
      82             : 
      83           3 : int HIP9011::getBandIndex(DEFINE_HIP_PARAMS) {
      84           3 :         float freq = getBand(FORWARD_HIP_PARAMS);
      85           3 :         int i = findIndexMsg("freq", bandFreqLookup, BAND_LOOKUP_SIZE, freq);
      86           3 :         if (i < 0)
      87           0 :                 i = 0;
      88           3 :         if (i > BAND_LOOKUP_SIZE - 1)
      89           0 :                 i = BAND_LOOKUP_SIZE - 1;
      90             : 
      91           3 :         return i;
      92             : }
      93             : 
      94           7 : int HIP9011::getGainIndex(DEFINE_HIP_PARAMS) {
      95           7 :         int i = findIndexMsg("fGain", gainLookupInReverseOrder, GAIN_LOOKUP_SIZE, GET_CONFIG_VALUE(hip9011Gain));
      96           7 :         if (i < 0)
      97           2 :                 i = 0;
      98           7 :         if (i > GAIN_LOOKUP_SIZE - 1)
      99           0 :                 i = GAIN_LOOKUP_SIZE - 1;
     100             : 
     101             :         /* reverse order */
     102           7 :         return GAIN_LOOKUP_SIZE - 1 - i;
     103             : }
     104             : 
     105             : /**
     106             :  * 'TC is typically TINT/(2*Pi*VOUT)'
     107             :  * Knock Sensor Training TPIC8101, page 24
     108             :  */
     109          69 : float HIP9011::getRpmByAngleWindowAndTimeUs(int timeUs, float p_angleWindowWidth) {
     110             :         /**
     111             :          * TINT = TC * 2 * PI * VOUT
     112             :          */
     113          69 :         float integrationTimeUs = timeUs * 2 * CONST_PI * HIP9011_ANALOG_OUTPUT_MAX;
     114             :         /**
     115             :          * rpm = 60 seconds / time
     116             :          * '60000000' because revolutions per MINUTE in uS conversion
     117             :          */
     118          69 :         float windowWidthMult = p_angleWindowWidth / 360.0f;
     119          69 :         return 60000000.0f / integrationTimeUs * windowWidthMult;
     120             : }
     121             : 
     122             : /**
     123             :  *
     124             :  * We know the set of possible integration times, we know the knock detection window width
     125             :  */
     126           2 : void HIP9011::prepareRpmLookup(void) {
     127             :         /**
     128             :          * out binary search method needs increasing order thus the reverse order here
     129             :          */
     130          66 :         for (int i = 0; i < INT_LOOKUP_SIZE; i++) {
     131          64 :                 rpmLookup[i] = getRpmByAngleWindowAndTimeUs(integratorValues[INT_LOOKUP_SIZE - i - 1], angleWindowWidth);
     132             :         }
     133           2 : }
     134             : 
     135           6 : int HIP9011::getIntegrationIndexByRpm(float rpm) {
     136           6 :         int i = findIndexMsg("getIbR", rpmLookup, INT_LOOKUP_SIZE, (rpm));
     137           6 :         return i == -1 ? INT_LOOKUP_SIZE - 1 : INT_LOOKUP_SIZE - i - 1;
     138             : }
     139             : 
     140           2 : void HIP9011::setAngleWindowWidth(DEFINE_HIP_PARAMS) {
     141           2 :         float new_angleWindowWidth =
     142             :                 GET_CONFIG_VALUE(knockDetectionWindowEnd) -
     143             :                 GET_CONFIG_VALUE(knockDetectionWindowStart);
     144           2 :         if (new_angleWindowWidth < 0) {
     145             : #if EFI_PROD_CODE
     146             :                 warning(ObdCode::CUSTOM_KNOCK_WINDOW, "invalid knock window");
     147             : #endif
     148           0 :                 new_angleWindowWidth = 0;
     149             :         }
     150             :         // float '==' is totally appropriate here
     151           2 :         if (angleWindowWidth == new_angleWindowWidth)
     152           1 :                 return; // exit if value has not change
     153           1 :         angleWindowWidth = new_angleWindowWidth;
     154           1 :         prepareRpmLookup();
     155             : }
     156             : 
     157           2 : void HIP9011::handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS)) {
     158             :         int ret;
     159             : 
     160           2 :         setAngleWindowWidth(FORWARD_HIP_PARAMS);
     161             : 
     162           2 :         int new_prescaler = GET_CONFIG_VALUE(hip9011PrescalerAndSDO);
     163           2 :         int new_integratorIdx = getIntegrationIndexByRpm(rpm);
     164           2 :         int new_gainIdx = getGainIndex(FORWARD_HIP_PARAMS);
     165           2 :         int new_bandIdx = getBandIndex(FORWARD_HIP_PARAMS);
     166             : 
     167           2 :         if (gainIdx != new_gainIdx) {
     168           1 :                 ret = sendCommand(SET_GAIN_CMD(new_gainIdx));
     169           1 :                 if (ret == 0)
     170           1 :                         gainIdx = new_gainIdx;
     171             :         }
     172           2 :         if (intergratorIdx != new_integratorIdx) {
     173           1 :                 ret = sendCommand(SET_INTEGRATOR_CMD(new_integratorIdx));
     174           1 :                 if (ret == 0)
     175           1 :                         intergratorIdx = new_integratorIdx;
     176             :         }
     177           2 :         if (bandIdx != new_bandIdx) {
     178           1 :                 ret = sendCommand(SET_BAND_PASS_CMD(new_bandIdx));
     179           1 :                 if (ret == 0)
     180           1 :                         bandIdx = new_bandIdx;
     181             :         }
     182           2 :         if (prescaler != new_prescaler) {
     183           1 :                 ret = sendCommand(SET_PRESCALER_CMD(new_prescaler));
     184           1 :                 if (ret == 0)
     185           1 :                         prescaler = new_prescaler;
     186             :         }
     187           2 : }
     188             : 
     189           0 : int HIP9011::cylinderToChannelIdx(int cylinder) {
     190             :         /* TODO: hip9011 inputs to bank mapping? */
     191           0 :         return getCylinderKnockBank(cylinder);
     192             : }
     193             : 
     194           0 : int HIP9011::handleChannel(DEFINE_HIP_PARAMS) {
     195             :         int ret;
     196             : 
     197             :         /* we did not receive any callback from spark logic with valid cylinder yet */
     198           0 :         if (cylinderNumber < 0)
     199           0 :                 return -1;
     200             : 
     201             :         /* find next firing cylinder */
     202             :         /* MAGIC +1 -1, couse getNextFiringCylinderId expect cylinders to start from 1 */
     203           0 :         expectedCylinderNumber = getNextFiringCylinderId((cylinderNumber + 1)) - 1;
     204             : 
     205           0 :         int nextChannelIdx = cylinderToChannelIdx(expectedCylinderNumber);
     206           0 :         if (nextChannelIdx == channelIdx)
     207           0 :                 return 0;
     208             : 
     209           0 :         ret = sendCommand(SET_CHANNEL_CMD(nextChannelIdx));
     210           0 :         if (ret)
     211           0 :                 return ret;
     212             : 
     213           0 :         channelIdx = nextChannelIdx;
     214             : 
     215           0 :         return 0;
     216             : }
     217             : 
     218           0 : int HIP9011::readValueAndHandleChannel(DEFINE_HIP_PARAMS) {
     219             :         int ret;
     220           0 :         uint8_t rx[2];
     221             : 
     222             :         /* we did not receive any callback from spark logic with valid cylinder yet */
     223           0 :         if (cylinderNumber < 0)
     224           0 :                 return -1;
     225             : 
     226             :         /* find next firing cylinder */
     227             :         /* MAGIC +1 -1, couse getNextFiringCylinderId expect cylinders to start from 1 */
     228           0 :         expectedCylinderNumber = getNextFiringCylinderId((cylinderNumber + 1)) - 1;
     229             : 
     230           0 :         int nextChannelIdx = cylinderToChannelIdx(expectedCylinderNumber);
     231             : 
     232             :         /* use cached values, let handleSettings take care of settings update */
     233             :         /* don't care about rx'ed data now */
     234           0 :         ret = sendCommand(SET_PRESCALER_CMD(prescaler));
     235           0 :         if (ret)
     236           0 :                 return ret;
     237             : 
     238             :         /* reply from Set Prescaler CMD -> D7 to D0 of the digital integrator output */
     239           0 :         ret = sendCommandGetReply(SET_CHANNEL_CMD(nextChannelIdx), &rx[0]);
     240           0 :         if (ret)
     241           0 :                 return ret;
     242             : 
     243             :         /* Same connand to get reply for previous command:
     244             :          * reply from Select the channel CMD -> D9 to D8 of difital integrator output and six zeroes */
     245           0 :         ret = sendCommandGetReply(SET_CHANNEL_CMD(nextChannelIdx), &rx[1]);
     246           0 :         if (ret)
     247           0 :                 return ret;
     248             : 
     249           0 :         channelIdx = nextChannelIdx;
     250             : 
     251             :         /* D9..D8 in high bits */
     252           0 :         rx[1] = (rx[1] >> 6) & 0x03;
     253             : 
     254             :         /* return digital integrator value */
     255           0 :         return (rx[0] | (rx[1]  << 8));
     256             : }

Generated by: LCOV version 1.14