rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
hip9011.cpp
Go to the documentation of this file.
1/**
2 * @file HIP9011.cpp
3 * @brief HIP9011/TPIC8101 driver
4 *
5 * Jan 2017 status:
6 * 1) seems to be kind of working - reacts to parameter changes and does produce variable output
7 * 2) only one (first) channel is currently used
8 * 3) engine control does not yet react to knock since very little actual testing - no engine runs with proven knock yet
9 *
10 *
11 * http://rusefi.com/forum/viewtopic.php?f=4&t=400
12 * http://rusefi.com/forum/viewtopic.php?f=5&t=778
13 *
14 * pin1 VDD
15 * pin2 GND
16 *
17 * pin8 Chip Select - CS
18 * pin11 Slave Data Out - MISO
19 * pin12 Slave Data In - MOSI
20 * pin13 SPI clock - SCLK
21 *
22 *
23 * http://www.ti.com/lit/ds/symlink/tpic8101.pdf
24 * http://www.intersil.com/content/dam/Intersil/documents/hip9/hip9011.pdf
25 * http://www.intersil.com/content/dam/Intersil/documents/an97/an9770.pdf
26 * http://e2e.ti.com/cfs-file/__key/telligent-evolution-components-attachments/00-26-01-00-00-42-36-40/TPIC8101-Training.pdf
27 *
28 * max SPI frequency: 5MHz max
29 *
30 * @date Nov 27, 2013
31 * @author Andrey Belomutskiy, (c) 2012-2020
32 * @Spilly
33 */
34
35#include "pch.h"
36
37#include "hardware.h"
38#include "trigger_central.h"
39#include "hip9011_logic.h"
40#include "hip9011.h"
41#include "knock_logic.h"
42
43#if EFI_PROD_CODE
44#include "mpu_util.h"
45#endif
46
47#if EFI_HIP_9011
48
49/*==========================================================================*/
50/* Local definitions. */
51/*==========================================================================*/
52
53/*==========================================================================*/
54/* Local variables and types. */
55/*==========================================================================*/
56
57#define PROTOCOL_HIP_NAME "HIP"
58
59static NamedOutputPin intHold(PROTOCOL_HIP_NAME);
60static NamedOutputPin Cs(PROTOCOL_HIP_NAME);
61
62class Hip9011Hardware : public Hip9011HardwareInterface {
63 int sendSyncCommand(uint8_t command, uint8_t *rx_ptr) override;
64
65public:
66 scheduling_s startTimer;
67 scheduling_s endTimer;
68
69private:
70 int checkResponseDefMode(uint8_t tx, uint8_t rx);
71 int checkResponseAdvMode(uint8_t tx, uint8_t rx);
72
73 uint8_t rep_mask;
74 uint8_t rep_value;
75};
76
77/* TODO: include following stuff in object */
78/* wake semaphore */
79static semaphore_t wake;
80
81static Hip9011Hardware hardware;
82
84
85#if EFI_HIP_9011_DEBUG
86 static float normalizedValue[HIP_INPUT_CHANNELS];
87 static float normalizedValueMax[HIP_INPUT_CHANNELS];
88#endif
89
90// SPI_CR1_BR_1 // 5MHz
91// SPI_CR1_CPHA Clock Phase
92// todo: nicer method which would mention SPI speed explicitly?
93
94#if EFI_PROD_CODE
95static SPIDriver *spi;
96
97static SPIConfig hipSpiCfg = {
98 .circular = false,
99#ifdef _CHIBIOS_RT_CONF_VER_6_1_
100 .end_cb = NULL,
101#else
102 .slave = false,
103 .data_cb = NULL,
104 .error_cb = NULL,
105#endif
106 .ssport = NULL,
107 .sspad = 0,
108 .cr1 =
109 SPI_CR1_8BIT_MODE |
110 SPI_CR1_MSTR |
111 SPI_CR1_CPHA |
112 //SPI_CR1_BR_1 // 5MHz
113 SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_BR_2,
114 .cr2 =
115 SPI_CR2_8BIT_MODE
116};
117#endif /* EFI_PROD_CODE */
118
119/*==========================================================================*/
120/* Forward declarations */
121/*==========================================================================*/
122
123#if EFI_HIP_9011_DEBUG
124 static void hip_addconsoleActions();
125#endif
126
127/*==========================================================================*/
128/* Local functions. */
129/*==========================================================================*/
130
131int Hip9011Hardware::checkResponseDefMode(uint8_t tx, uint8_t rx) {
132 /* in default SPI mode SDO is directly equals the SDI (echo function) */
133 if (tx == rx) {
134 return 0;
135 } else {
136 return -1;
137 }
138}
139
140int Hip9011Hardware::checkResponseAdvMode(uint8_t tx, uint8_t rx) {
141 int ret = 0;
142
143 /* check reply */
144 if ((rx & rep_mask) != rep_value)
145 ret = -1;
146
147 /* extract mask and value for next reply */
148 if ((tx & 0xe0) == SET_PRESCALER_CMD(0)){
149 /* D7 to D0 of digital integrator output */
150 rep_mask = 0x00;
151 rep_value = 0x00;
152 } else if ((tx & 0xfe) == SET_CHANNEL_CMD(0)) {
153 /* D9 to D8 of digital integrator output and six zeroes */
154 rep_mask = 0x3f;
155 rep_value = 0x00;
156 } else if ((tx & 0xc0) == SET_BAND_PASS_CMD(0)) {
157 rep_mask = 0xff;
158 rep_value = SET_BAND_PASS_REP;
159 } else if ((tx & 0xc0) == SET_GAIN_CMD(0)) {
160 rep_mask = 0xff;
161 rep_value = SET_GAIN_REP;
162 } else if ((tx & 0xe0) == SET_INTEGRATOR_CMD(0)) {
163 rep_mask = 0xff;
164 rep_value = SET_INTEGRATOR_REP;
165 } else if ((tx & 0xff) == SET_ADVANCED_MODE_CMD) {
166 rep_mask = 0xff;
167 rep_value = SET_ADVANCED_MODE_REP;
168 } else {
169 /* unknown */
170 rep_mask = 0x00;
171 rep_value = 0x00;
172 }
173
174 return ret;
175}
176
177int Hip9011Hardware::sendSyncCommand(uint8_t tx, uint8_t *rx_ptr) {
178 int ret;
179 uint8_t rx;
180
181 /* Acquire ownership of the bus. */
182 spiAcquireBus(spi);
183 /* Setup transfer parameters. */
184 spiStart(spi, &hipSpiCfg);
185 /* Slave Select assertion. */
186 spiSelect(spi);
187 /* Transfer */
188 rx = spiPolledExchange(spi, tx);
189 /* Slave Select de-assertion. */
190 spiUnselect(spi);
191 /* Ownership release. */
192 spiReleaseBus(spi);
193 /* received data */
194 if (rx_ptr)
195 *rx_ptr = rx;
196 /* check response */
197 if (instance.adv_mode)
198 ret = checkResponseAdvMode(tx, rx);
199 else
200 ret = checkResponseDefMode(tx, rx);
201
202 #if EFI_HIP_9011_DEBUG
203 /* statistic counters */
204 if (ret)
206 else
208 #endif
209
210 return ret;
211}
212
213static int hip_wake_driver()
214{
215 /* Entering a reentrant critical zone.*/
216 syssts_t sts = chSysGetStatusAndLockX();
217 chSemSignalI(&wake);
218 if (!port_is_isr_context()) {
219 /**
220 * chSemSignalI above requires rescheduling
221 * interrupt handlers have implicit rescheduling
222 */
223 chSchRescheduleS();
224 }
225 /* Leaving the critical zone.*/
226 chSysRestoreStatusX(sts);
227
228 return 0;
229}
230
231static void startIntegration(HIP9011 *hip) {
232 if (hip->state == READY_TO_INTEGRATE) {
233 /**
234 * SPI communication is only allowed while not integrating, so we postpone the exchange
235 * until we are done integrating
236 */
237 hip->state = IS_INTEGRATING;
239 } else {
240 #if EFI_HIP_9011_DEBUG
241 hip->overrun++;
242 #endif
243 }
244}
245
246static void endIntegration(HIP9011 *hip) {
247 /**
248 * isIntegrating could be 'false' if an SPI command was pending thus we did not integrate during this
249 * engine cycle
250 */
251 if (hip->state == IS_INTEGRATING) {
252 intHold.setLow();
253
255
256 if (instance.adv_mode) {
257 /* read value over SPI in thread mode */
258 hip->state = NOT_READY;
260 } else {
261 /* wait for ADC samples */
263 }
264 }
265}
266
267void onStartKnockSampling(uint8_t /*cylinderIndex*/, float /*samplingTimeSeconds*/, uint8_t /*channelIdx*/) {
268 /* TODO: @dron0gus: not sure if we need the expectedCylinderNumber logic at all
269
270 Something like this might be right:
271
272 startIntegration(&instance);
273
274 efitick_t windowLength = USF2NT(1e6 * samplingTimeSeconds);
275
276 engine->executor.scheduleByTimestampNt("knock", &hardware.endTimer, getTimeNowNt() + windowLength, { endIntegration, &instance });
277 */
278}
279
280/**
281 * Ignition callback used to start HIP integration and schedule finish
282 */
283void hip9011_onFireEvent(uint8_t cylinderNumber, efitick_t nowNt) {
285 return;
286
287 /* We are not checking here for READY_TO_INTEGRATE state as
288 * previous integration may be still in progress, while
289 * we are scheduling next integration start only
290 * knockDetectionWindowStart from now.
291 * Check for correct state will be done at startIntegration () */
292
293 if (cylinderNumber == instance.expectedCylinderNumber) {
294 /* save currect cylinder */
295 instance.cylinderNumber = cylinderNumber;
296
297 /* smart books says we need to sence knock few degrees after TDC
298 * currently I have no idea how to hook to cylinder TDC in correct way.
299 * So schedule start of integration + knockDetectionWindowStart from fire event
300 * Keep this is mind when setting knockDetectionWindowStart */
301 scheduleByAngle(&hardware.startTimer, nowNt,
303 { startIntegration, &instance });
304
305 scheduleByAngle(&hardware.endTimer, nowNt,
307 { endIntegration, &instance });
308 } else {
309 #if EFI_HIP_9011_DEBUG
310 /* out of sync */
313 #endif
314 /* save currect cylinder */
315 instance.cylinderNumber = cylinderNumber;
316 /* Skip integration, call driver task to prepare for next cylinder */
319 }
320}
321
322void hipAdcCallback(float volts) {
323 /* we read in digital mode */
324 if (instance.adv_mode)
325 return;
328 } else if (instance.state == WAITING_FOR_RESULT_ADC) {
329 /* offload calculations to driver thread */
330 if (instance.channelIdx < HIP_INPUT_CHANNELS) {
331 /* normalize to 0..HIP9011_DIGITAL_OUTPUT_MAX */
333 volts * HIP9011_DIGITAL_OUTPUT_MAX / HIP9011_ANALOG_OUTPUT_MAX;
334 }
337 }
338}
339
340static int hip_testAdvMode() {
341 int ret;
342 uint8_t ret0, ret1, ret2;
343
344 /* do not care about configuration values, we meed replyes only.
345 * correct values will be uploaded later */
346
347 /* A control byte is written to the SDI and shifted with the MSB
348 * first. The response byte on the SDO is shifted out with the MSB
349 * first. The response byte corresponds to the previous command.
350 * Therefore, the SDI shifts in a control byte n and shifts out a
351 * response command byte n − 1. */
352 ret = instance.hw->sendSyncCommand(SET_BAND_PASS_CMD(0), NULL);
353 if (ret)
354 return ret;
355 ret = instance.hw->sendSyncCommand(SET_GAIN_CMD(0), &ret0);
356 if (ret)
357 return ret;
358 ret = instance.hw->sendSyncCommand(SET_INTEGRATOR_CMD(0), &ret1);
359 if (ret)
360 return ret;
361 ret = instance.hw->sendSyncCommand(SET_INTEGRATOR_CMD(0), &ret2);
362 if (ret)
363 return ret;
364
365 /* magic reply bytes from DS Table 2 */
366 if ((ret0 == SET_BAND_PASS_REP) &&
367 (ret1 == SET_GAIN_REP) &&
368 (ret2 == SET_INTEGRATOR_REP))
369 return 0;
370
371 return -1;
372}
373
374static int hip_init() {
375 int ret;
376
377 /* Just to enable SDO */
378 ret = instance.hw->sendSyncCommand(SET_PRESCALER_CMD(instance.prescaler), NULL);
379 if (ret) {
380 /* NOTE: hip9011/tpic8101 can be in default or advanced mode at this point
381 * If we supposed not to support advanced mode this is definitely error */
383 return ret;
384 }
385
386 /* ...othervice or when no error is reported lets try to switch to advanced mode */
388 uint8_t rx = 0x00;
389 /* enable advanced mode */
390 instance.hw->sendSyncCommand(SET_ADVANCED_MODE_CMD, NULL);
391
392 /* send enable advanced mode again... */
393 instance.hw->sendSyncCommand(SET_ADVANCED_MODE_CMD, NULL);
394
395 /* to get reply on next command */
396 instance.hw->sendSyncCommand(SET_ADVANCED_MODE_CMD, &rx);
397 if (rx != SET_ADVANCED_MODE_REP) {
398 /* this is really a communication problem */
399 return -1;
400 }
401
402 /* now we should be in advanced mode... if chip supports...
403 * set advanced mode flag now so checkResponse will switch to
404 * advanced mode checkig (not implemented) */
405 instance.adv_mode = true;
406
407 ret = hip_testAdvMode();
408 if (ret) {
409 warning(ObdCode::CUSTOM_OBD_KNOCK_PROCESSOR, "TPIC/HIP does not support advanced mode");
410 instance.adv_mode = false;
411 return -1;
412 }
413 }
414
415 #if EFI_HIP_9011_DEBUG
416 /* reset counters now */
419 instance.samples = 0;
420 instance.overrun = 0;
421 instance.unsync = 0;
422 #endif
423
425
426 return 0;
427}
428
429static THD_WORKING_AREA(hipThreadStack, UTILITY_THREAD_STACK_SIZE);
430
431static msg_t hipThread(void *arg) {
432 int ret;
433 UNUSED(arg);
434 chRegSetThreadName("hip9011 worker");
435
436 /* This strange code was here before me.
437 * Not sure why we need it */
438#if 0
439 /* Acquire ownership of the bus. */
440 spiAcquireBus(spi);
441 // some time to let the hardware start
442 Cs.setValue(true);
443 chThdSleepMilliseconds(100);
444 Cs.setValue(false);
445 chThdSleepMilliseconds(100);
446 Cs.setValue(true);
447 /* Ownership release. */
448 spiReleaseBus(spi);
449
450 chThdSleepMilliseconds(100);
451#endif
452
453 do {
454 /* retry until success */
455 ret = hip_init();
456 if (ret) {
457 warning(ObdCode::CUSTOM_OBD_KNOCK_PROCESSOR, "TPIC/HIP does not respond: %d", ret);
458 chThdSleepMilliseconds(10 * 1000);
459 }
460 } while (ret);
461
462 while (1) {
463 msg_t msg;
464
465 /* load new/updated settings */
466 instance.handleSettings(Sensor::getOrZero(SensorType::Rpm) DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
467 /* in advanced more driver will set channel while reading integrator value */
468 if (!instance.adv_mode) {
469 /* switch input channel */
470 instance.handleChannel(DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
471 }
472 /* State */
474
475 msg = chSemWaitTimeout(&wake, TIME_INFINITE);
476 if (msg == MSG_TIMEOUT) {
477 /* ??? */
478 } else {
479 int rawValue;
480 /* check now, before readValueAndHandleChannel did not overwrite expectedCylinderNumber */
481 bool correctCylinder = (instance.cylinderNumber == instance.expectedCylinderNumber);
482
483 /* this needs to be called in any case to set proper channel for next cycle */
484 if (instance.adv_mode) {
485 rawValue = instance.readValueAndHandleChannel(DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
486
487 /* spi communication issue? */
488 if (rawValue < 0)
489 continue;
490 }
491
492 /* check that we know channel for current measurement */
493 int idx = instance.channelIdx;
494 if (!(idx < HIP_INPUT_CHANNELS))
495 continue;
496
497 float knockNormalized = 0.0f;
498 float knockVolts = 0.0f;
499
500 /* calculations */
501 if (instance.adv_mode) {
502 instance.rawValue[idx] = rawValue;
503 } else {
504 /* get value stored by callback */
505 rawValue = instance.rawValue[idx];
506 }
507 /* convert 10 bit integer value to 0.0 .. 1.0 float */
508 knockNormalized = ((float)rawValue) / HIP9011_DIGITAL_OUTPUT_MAX;
509 /* convert to magic volts
510 * TODO: remove conversion to volts */
511 knockVolts = knockNormalized * HIP9011_ANALOG_OUTPUT_MAX;
512
513 /* Check for correct cylinder/input */
514 if (correctCylinder) {
515 // TODO: convert knock level to dBv
516 engine->module<KnockController>()->onKnockSenseCompleted(instance.cylinderNumber, knockVolts, instance.knockSampleTimestamp);
517
518 #if EFI_HIP_9011_DEBUG
519 /* debug */
520 normalizedValue[idx] = knockNormalized;
521 normalizedValueMax[idx] = std::max(knockNormalized, normalizedValueMax[idx]);
522 /* counters */
524 #endif
525 } else {
526 /* out of sync event already calculated, nothing to do */
527 }
528 }
529 }
530
531 return -1;
532}
533
534/*==========================================================================*/
535/* Exported functions. */
536/*==========================================================================*/
537
539 intHold.deInit();
540 Cs.deInit();
541#if EFI_PROD_CODE
542 spi = NULL;
543 hipSpiCfg.ssport = NULL;
544#endif
545}
546
549 intHold.setValue(1);
551 Cs.setValue(1);
552
553#if EFI_PROD_CODE
555 if (spi == NULL) {
556 // error already reported
557 return;
558 }
561#endif /* EFI_PROD_CODE */
562}
563
566 return;
567
569
570 /* load settings */
572
573 efiPrintf("Starting HIP9011/TPIC8101 driver");
574
575 /* init semaphore */
576 chSemObjectInit(&wake, 10);
577 chThdCreateStatic(hipThreadStack, sizeof(hipThreadStack), PRIO_HIP9011, (tfunc_t)(void*) hipThread, NULL);
578
579 #if EFI_HIP_9011_DEBUG
581 #endif
582}
583
584/*==========================================================================*/
585/* Debug functions. */
586/*==========================================================================*/
587
588#if EFI_HIP_9011_DEBUG
589
590static const char *hip_state_names[] =
591{
592 "Not ready/calculating",
593 "Ready for integration",
594 "Integrating",
595 "Waiting for first ADC sample",
596 "Waiting for second ADC sample"
597};
598
599static void showHipInfo() {
601 efiPrintf("hip9011 driver not active");
602 return;
603 }
604
605 efiPrintf("HIP9011: enabled %s",
607
609 return;
610 }
611
612 efiPrintf(" State %s",
614
615 efiPrintf(" Advanced mode: enabled %d used %d",
618
619 efiPrintf(" Input Ch %d (cylinder %d next %d)",
623
624 efiPrintf(" Cyl bore %.2fmm freq %.2fkHz band idx 0x%x",
626 instance.getBand(PASS_HIP_PARAMS),
628
629 efiPrintf(" Integrator %d uS idx 0x%x RPM %d",
632
633 efiPrintf(" Gain %.2f idx 0x%x",
636
637 efiPrintf(" PaSDO=0x%x",
639
640 efiPrintf(" IntHold %s (mode 0x%x)",
643
644 efiPrintf(" Spi %s CS %s (mode 0x%x)",
648
649#if EFI_PROD_CODE
651#endif /* EFI_PROD_CODE */
652
653 efiPrintf(" SPI: good response %d incorrect response %d",
656
657 efiPrintf(" Counters: samples %d overruns %d sync miss %d",
659
660 efiPrintf(" Window start %.2f end %.2f",
663
664 if (!instance.adv_mode) {
665 efiPrintf(" Adc input %d (%.2f V)",
668 }
669
670 for (int i = 0; i < HIP_INPUT_CHANNELS; i++) {
671 efiPrintf(" input[%d] %d -> %.3f (max %.3f)",
672 i,
676 normalizedValueMax[i] = 0.0;
677 }
678}
679
680static void setPrescaler(int value) {
682}
683
684static void setHipGain(float value) {
686 showHipInfo();
687}
688
690 addConsoleAction("hipinfo", showHipInfo);
691 addConsoleActionF("set_gain", setHipGain);
692 addConsoleActionI("set_hip_prescaler", setPrescaler);
693}
694
695#endif /* EFI_HIP_9011_DEBUG */
696
697#endif /* EFI_HIP_9011 */
float adcGetRawVoltage(const char *msg, adc_channel_e hwChannel)
const char * getSpi_device_e(spi_device_e value)
constexpr auto & module()
Definition engine.h:189
float getBand(DEFINE_HIP_PARAMS)
uint8_t channelIdx
int getIntegrationTimeByIndex(int index)
efitick_t knockSampleTimestamp
uint8_t intergratorIdx
void handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS))
int8_t cylinderNumber
int correctResponsesCount
int8_t expectedCylinderNumber
hip_state_e state
uint8_t bandIdx
int readValueAndHandleChannel(DEFINE_HIP_PARAMS)
int handleChannel(DEFINE_HIP_PARAMS)
uint8_t prescaler
Hip9011HardwareInterface * hw
uint8_t gainIdx
uint16_t rpmLookup[INT_LOOKUP_SIZE]
uint16_t rawValue[HIP_INPUT_CHANNELS]
bool adv_mode
int invalidResponsesCount
virtual int sendSyncCommand(unsigned char command, uint8_t *rx_ptr)=0
virtual void setLow(const char *msg)
Definition efi_gpio.cpp:450
virtual void setHigh(const char *msg)
Definition efi_gpio.cpp:428
void deInit()
Definition efi_gpio.cpp:788
void initPin(const char *msg, brain_pin_e brainPin, pin_output_mode_e outputMode, bool forceInitWithFatalError=false)
Definition efi_gpio.cpp:697
void setValue(const char *msg, int logicValue, bool isForce=false)
Definition efi_gpio.cpp:590
static float getOrZero(SensorType type)
Definition sensor.h:83
void addConsoleActionF(const char *token, VoidFloat callback)
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
void addConsoleActionI(const char *token, VoidInt callback)
Register a console command with one Integer parameter.
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
const char * boolToString(bool value)
Definition efilib.cpp:18
efitick_t getTimeNowNt()
Definition efitime.cpp:19
static Engine *const engine
Definition engine.h:386
static constexpr engine_configuration_s * engineConfiguration
bool warning(ObdCode code, const char *fmt,...)
void printSpiConfig(const char *msg, spi_device_e device)
Definition hardware.cpp:250
SPIDriver * getSpiDevice(spi_device_e spiDevice)
Definition hardware.cpp:143
void initHip9011()
Definition hip9011.cpp:564
static THD_WORKING_AREA(hipThreadStack, UTILITY_THREAD_STACK_SIZE)
void onStartKnockSampling(uint8_t, float, uint8_t)
Definition hip9011.cpp:267
static NamedOutputPin intHold(PROTOCOL_HIP_NAME)
void startHip9011_pins()
Definition hip9011.cpp:547
static void startIntegration(HIP9011 *hip)
Definition hip9011.cpp:231
static int hip_testAdvMode()
Definition hip9011.cpp:340
static int hip_wake_driver()
Definition hip9011.cpp:213
static float normalizedValue[HIP_INPUT_CHANNELS]
Definition hip9011.cpp:86
static float normalizedValueMax[HIP_INPUT_CHANNELS]
Definition hip9011.cpp:87
static int hip_init()
Definition hip9011.cpp:374
static SPIConfig hipSpiCfg
Definition hip9011.cpp:97
static semaphore_t wake
Definition hip9011.cpp:79
void hip9011_onFireEvent(uint8_t cylinderNumber, efitick_t nowNt)
Definition hip9011.cpp:283
void stopHip9011_pins()
Definition hip9011.cpp:538
static void setHipGain(float value)
Definition hip9011.cpp:684
void hipAdcCallback(float volts)
Definition hip9011.cpp:322
static const char * hip_state_names[]
Definition hip9011.cpp:590
static void endIntegration(HIP9011 *hip)
Definition hip9011.cpp:246
static msg_t hipThread(void *arg)
Definition hip9011.cpp:431
static void showHipInfo()
Definition hip9011.cpp:599
static void hip_addconsoleActions()
Definition hip9011.cpp:689
static SPIDriver * spi
Definition hip9011.cpp:95
static NamedOutputPin Cs(PROTOCOL_HIP_NAME)
static Hip9011Hardware hardware
Definition hip9011.cpp:81
static void setPrescaler(int value)
Definition hip9011.cpp:680
HIP9011/TPIC8101 driver.
@ NOT_READY
@ READY_TO_INTEGRATE
@ WAITING_FOR_RESULT_ADC
@ IS_INTEGRATING
@ WAITING_FOR_ADC_TO_SKIP
UNUSED(samplingTimeSeconds)
@ CUSTOM_OBD_KNOCK_PROCESSOR
const char * hwPortname(brain_pin_e brainPin)
efitick_t scheduleByAngle(scheduling_s *timer, efitick_t nowNt, angle_t angle, action_s action)
HIP9011 instance