rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
kline.cpp
Go to the documentation of this file.
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
11size_t readWhileGives(ByteSource source, uint8_t *buffer, size_t bufferSize) {
12 size_t totalBytes = 0;
13 while (totalBytes < bufferSize) {
14 size_t readThisTime = source(&buffer[totalBytes], bufferSize - totalBytes);
15 if (readThisTime == 0) {
16 // looks like idle gap
17 break;
18 }
19 totalBytes += readThisTime;
20 }
21 return totalBytes;
22}
23
24#ifdef EFI_KLINE
25
26static uint8_t kvalues[8];
27
28#define HONDA_K_BCM_STATUS_NIBBLE 0x0
29#define HONDA_K_BCM_REQ_NIBBLE 0x1
30
32
33static 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;
41 efiPrintf("honda status packet with 0x%02x 0x%02x state %d", statusByte1, statusByte2, kAcRequestState);
42 }
43}
44
45static SerialDriver* const klDriver = &KLINE_SERIAL_DEVICE;
46static THD_WORKING_AREA(klThreadStack, UTILITY_THREAD_STACK_SIZE);
47
48static int totalBytes = 0;
49
50void 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
69// efiPrintf("ignoreRecentTransmit %d", ignoreRecentTransmit);
70 }
71
72 // to begin with just write byte to console
73 if (len > 0) {
75 efiPrintf("kline: got count 0x%02x", len);
76 }
77 for (size_t i =0;i<len;i++) {
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]) {
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) {
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)) {
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
128 efiPrintf("kline doSend");
129 }
130 int positiveCltWithHighishValueInCaseOfSensorIssue = maxI(1,
131#ifdef HW_HELLEN_HONDA
132 /* temporary while we are playing with calibration */
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
158#ifdef EFI_KLINE
160 return;
161 }
162#if EFI_PROD_CODE
163 efiSetPadMode("K-Line UART RX", Gpio::KLINE_SERIAL_DEVICE_RX, PAL_MODE_ALTERNATE(TS_SERIAL_AF));
164 efiSetPadMode("K-Line UART TX", Gpio::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
177 engineConfiguration->kLineBaudRate = KLINE_BAUD_RATE;
179
180 sdStart(klDriver, &cfg);
181#endif // EFI_KLINE
182}
183
184void stopKLine() {
185#ifdef EFI_KLINE
186#if EFI_PROD_CODE
188 efiSetPadUnused(Gpio::KLINE_SERIAL_DEVICE_RX);
189 efiSetPadUnused(Gpio::KLINE_SERIAL_DEVICE_TX);
190
191 sdStop(klDriver);
192 }
193
194#endif /* EFI_PROD_CODE */
195#endif // EFI_KLINE
196}
197
198void initKLine() {
200 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", [](){
214 efiPrintf("kline send %d", engineConfiguration->kLineDoHondaSend);
215 });
216 addConsoleAction("klineno", [](){
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}
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
virtual SensorResult get() const =0
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
void addConsoleActionII(const char *token, VoidIntInt callback)
Register a console command with two Integer parameters.
uint8_t crc_hondak_calc(const uint8_t *data, size_t len)
engine_configuration_s & activeConfiguration
static constexpr persistent_config_s * config
static constexpr engine_configuration_s * engineConfiguration
void efiSetPadUnused(brain_pin_e brainPin)
Definition io_pins.cpp:20
void stopKLine()
Definition kline.cpp:184
void startKLine()
Definition kline.cpp:157
void kLineThread(void *)
Definition kline.cpp:50
static int totalBytes
Definition kline.cpp:48
bool kAcRequestState
Definition kline.cpp:31
static THD_WORKING_AREA(klThreadStack, UTILITY_THREAD_STACK_SIZE)
static void handleHonda(uint8_t *bufferIn)
Definition kline.cpp:33
void initKLine()
Definition kline.cpp:198
size_t readWhileGives(ByteSource source, uint8_t *buffer, size_t bufferSize)
Definition kline.cpp:11
static SerialDriver *const klDriver
Definition kline.cpp:45
static uint8_t kvalues[8]
Definition kline.cpp:26
size_t(* ByteSource)(uint8_t *, int)
Definition kline.h:23
static BigBufferHandle buffer