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