LCOV - code coverage report
Current view: top level - firmware/hw_layer - kline.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 15 15 100.0 %
Date: 2024-07-27 05:50:15 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /**
       2             :  * this file is mostly about SEFMJ early 2000s specific honda K-line protocol
       3             :  * https://rusefi.com/forum/viewtopic.php?f=4&t=2514
       4             :  */
       5             : 
       6             : #include "pch.h"
       7             : #include "kline.h"
       8             : #include "hellen_meta.h"
       9             : #include "crc8hondak.h"
      10             : 
      11           1 : size_t readWhileGives(ByteSource source, uint8_t *buffer, size_t bufferSize) {
      12           1 :         size_t totalBytes = 0;
      13          12 :         while (totalBytes < bufferSize) {
      14          12 :            size_t readThisTime = source(&buffer[totalBytes], bufferSize - totalBytes);
      15          12 :            if (readThisTime == 0) {
      16             :                 // looks like idle gap
      17           1 :                 break;
      18             :            }
      19          11 :            totalBytes += readThisTime;
      20             :         }
      21           1 :     return totalBytes;
      22             : }
      23             : 
      24             : #ifdef EFI_KLINE
      25             : 
      26             : static uint8_t kvalues[8];
      27             : 
      28             : #define HONDA_K_BCM_STATUS_NIBBLE 0x0
      29             : #define HONDA_K_BCM_REQ_NIBBLE 0x1
      30             : 
      31             : bool kAcRequestState;
      32             : 
      33             : static void handleHonda(uint8_t *bufferIn) {
      34             : 
      35             :     // no headlights 0x40, with headlights 0x60
      36             :         uint8_t statusByte1 = bufferIn[1];
      37             :         // no cabin blower 0x06, with blower 0x86
      38             :         uint8_t statusByte2 = bufferIn[2];
      39             :     kAcRequestState = statusByte2 & 0x80;
      40             :     if (engineConfiguration->verboseKLine) {
      41             :         efiPrintf("honda status packet with 0x%02x 0x%02x state %d", statusByte1, statusByte2, kAcRequestState);
      42             :     }
      43             : }
      44             : 
      45             : static SerialDriver* const klDriver = &KLINE_SERIAL_DEVICE;
      46             : static THD_WORKING_AREA(klThreadStack, UTILITY_THREAD_STACK_SIZE);
      47             : 
      48             : static int totalBytes = 0;
      49             : 
      50             : void kLineThread(void*) {
      51             :     // due to single wire we read everything we've transmitted
      52             :     bool ignoreRecentTransmit = false;
      53             :     int sendCounter = 0;
      54             :     while (1) {
      55             : 
      56             :         /**
      57             :          * under the hood there is SERIAL_BUFFERS_SIZE which we hope to help us
      58             :          */
      59             : 
      60             :         uint8_t bufferIn[16];
      61             :         // a bit of a busy read open question if this would affect performance?
      62             :         // on 2003 Honda for instance the bus seems to be 70%-ish busy. 9600 baud is 1.04ms per byte, a bit below 1kHz
      63             :         ByteSource serialSource = [] (uint8_t * buffer, int maxSize) {
      64             :             return chnReadTimeout(klDriver,buffer, maxSize, TIME_US2I(engineConfiguration->kLinePeriodUs));
      65             :         };
      66             :         size_t len = readWhileGives(serialSource, bufferIn, sizeof(bufferIn));
      67             : 
      68             :                     if (engineConfiguration->verboseKLine) {
      69             : //                        efiPrintf("ignoreRecentTransmit %d", ignoreRecentTransmit);
      70             :                     }
      71             : 
      72             :         // to begin with just write byte to console
      73             :         if (len > 0) {
      74             :             if (engineConfiguration->verboseKLine) {
      75             :                 efiPrintf("kline: got count 0x%02x", len);
      76             :             }
      77             :             for (size_t i =0;i<len;i++) {
      78             :                 if (engineConfiguration->verboseKLine) {
      79             :                     efiPrintf("kline: got 0x%02x", bufferIn[i]);
      80             :                 }
      81             :                 totalBytes++;
      82             :             }
      83             :             if (len > 1) {
      84             :                 int crc = crc_hondak_calc(bufferIn, len - 1);
      85             :                 uint8_t low = bufferIn[0] & 0xF;
      86             :                 if (crc == bufferIn[len - 1]) {
      87             :                     if (engineConfiguration->verboseKLine) {
      88             :                         efiPrintf("happy CRC 0x%02x", crc);
      89             :                     }
      90             :                     if (low == HONDA_K_BCM_STATUS_NIBBLE) {
      91             :                         handleHonda(bufferIn);
      92             :                     }
      93             : 
      94             :                     if (low == HONDA_K_BCM_REQ_NIBBLE) {
      95             :                         if (engineConfiguration->verboseKLine) {
      96             :                             efiPrintf("BCM request 0x%02x", bufferIn[0]);
      97             :                         }
      98             :                     }
      99             : 
     100             :                 } else if (low == HONDA_K_BCM_STATUS_NIBBLE && bufferIn[4] == crc_hondak_calc(bufferIn, 4)) {
     101             :                     if (engineConfiguration->verboseKLine) {
     102             :                         efiPrintf("hack for now, happy CRC 0x%02x", crc);
     103             :                     }
     104             :                     handleHonda(bufferIn);
     105             :                 }
     106             : 
     107             : 
     108             :                 if (engineConfiguration->kLineDoHondaSend && !ignoreRecentTransmit) {
     109             :                     sendCounter++;
     110             : #define OUT_SIZE 6
     111             : //                      const uint8_t out2[] = {0x2, 0x0, 0x0, 0x50, 0x0, 0x0};
     112             :                     //static_assert(sizeof(out2) == OUT_SIZE);
     113             : //                      const uint8_t outB[] = {0x42, 0x0, 0x0, 0x50, 0x0, 0x0};
     114             : //                      static_assert(sizeof(outB) == OUT_SIZE);
     115             :                         //const uint8_t *out = (sendCounter % 3 == 0) ? outB : out2;
     116             : //                      const uint8_t *out = out2;
     117             : 
     118             :                     if (sendCounter % 30 == 0) {
     119             :                         // no idea what this, maybe "i am running"?
     120             :                         kvalues[0] = 0x82;
     121             :                         kvalues[2] = 0x10;
     122             :                     } else {
     123             :                         kvalues[0] = 0x2;
     124             :                         kvalues[2] = 0;
     125             :                     }
     126             : 
     127             :                     if (engineConfiguration->verboseKLine) {
     128             :                         efiPrintf("kline doSend");
     129             :                     }
     130             :                     int positiveCltWithHighishValueInCaseOfSensorIssue = maxI(1,
     131             : #ifdef HW_HELLEN_HONDA
     132             :                         /* temporary while we are playing with calibration */
     133             :                         config->hondaKcltGaugeAdder
     134             : #else
     135             :   50
     136             : #endif
     137             :                          + Sensor::get(SensorType::Clt).value_or(140)
     138             :                     );
     139             :     // 125 about horizontal
     140             :     // 162 points at red mark, looks like gauge has hysteresis?
     141             :     // value 200 way above red mark
     142             :                     kvalues[3] = positiveCltWithHighishValueInCaseOfSensorIssue;
     143             : 
     144             :                     chnWrite(klDriver, (const uint8_t *)kvalues, OUT_SIZE);
     145             :                     crc = crc_hondak_calc(kvalues, OUT_SIZE);
     146             :                     chnWrite(klDriver, (const uint8_t *)&crc, 1);
     147             :                     ignoreRecentTransmit = true;
     148             :                 } else {
     149             :                     ignoreRecentTransmit = false;
     150             :                 }
     151             :             }
     152             :         }
     153             :     }
     154             : }
     155             : #endif // EFI_KLINE
     156             : 
     157         161 : void startKLine() {
     158             : #ifdef EFI_KLINE
     159             :     if (!engineConfiguration->enableKline) {
     160             :         return;
     161             :     }
     162             : #if EFI_PROD_CODE
     163             :         efiSetPadMode("K-Line UART RX", KLINE_SERIAL_DEVICE_RX, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
     164             :         efiSetPadMode("K-Line UART TX", KLINE_SERIAL_DEVICE_TX, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
     165             : #endif /* EFI_PROD_CODE */
     166             : 
     167             :         static SerialConfig cfg = {
     168             :                 #if EFI_PROD_CODE
     169             :                         .speed = 0,
     170             :                         .cr1 = 0,
     171             :                         .cr2 = USART_CR2_STOP1_BITS | USART_CR2_LINEN,
     172             :                         .cr3 = 0
     173             :                 #endif // EFI_PROD_CODE
     174             :         };
     175             : 
     176             :     if (engineConfiguration->kLineBaudRate < 100)
     177             :         engineConfiguration->kLineBaudRate = KLINE_BAUD_RATE;
     178             :     cfg.speed = engineConfiguration->kLineBaudRate;
     179             : 
     180             :         sdStart(klDriver, &cfg);
     181             : #endif // EFI_KLINE
     182         161 : }
     183             : 
     184         161 : void stopKLine() {
     185             : #ifdef EFI_KLINE
     186             : #if EFI_PROD_CODE
     187             :     if (activeConfiguration.enableKline) {
     188             :             efiSetPadUnused(KLINE_SERIAL_DEVICE_RX);
     189             :             efiSetPadUnused(KLINE_SERIAL_DEVICE_TX);
     190             : 
     191             :             sdStop(klDriver);
     192             :         }
     193             : 
     194             : #endif /* EFI_PROD_CODE */
     195             : #endif // EFI_KLINE
     196         161 : }
     197             : 
     198         353 : void initKLine() {
     199         353 :     if (!engineConfiguration->enableKline) {
     200         353 :         return;
     201             :     }
     202             : #ifdef EFI_KLINE
     203             :         startKLine();
     204             : 
     205             :     memset(kvalues, 0, sizeof(kvalues));
     206             :     kvalues[0] = 0x2;
     207             : 
     208             :     chThdCreateStatic(klThreadStack, sizeof(klThreadStack), NORMALPRIO + 1, kLineThread, nullptr);
     209             :     addConsoleAction("kline", [](){
     210             :         efiPrintf("kline totalBytes %d", totalBytes);
     211             :     });
     212             :     addConsoleAction("klineyes", [](){
     213             :         engineConfiguration->kLineDoHondaSend = true;
     214             :         efiPrintf("kline send %d", engineConfiguration->kLineDoHondaSend);
     215             :     });
     216             :     addConsoleAction("klineno", [](){
     217             :         engineConfiguration->kLineDoHondaSend = false;
     218             :         efiPrintf("kline send %d", engineConfiguration->kLineDoHondaSend);
     219             :     });
     220             :     addConsoleActionII("temp_k", [](int index, int value) {
     221             :         kvalues[index] = value;
     222             :     });
     223             : 
     224             : #endif // EFI_KLINE
     225             : }

Generated by: LCOV version 1.14