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 175 : 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 175 : }
183 :
184 175 : 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 175 : }
197 :
198 497 : void initKLine() {
199 497 : if (!engineConfiguration->enableKline) {
200 497 : 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 : }
|