180 lines
4.9 KiB
C++
180 lines
4.9 KiB
C++
/*
|
|
* sent.cpp
|
|
*
|
|
* SENT protocol decoder
|
|
*
|
|
* TODO support MAF sensors like 04E906051 see https://github.com/rusefi/rusefi-hardware/issues/146
|
|
*
|
|
* @date Oct 01, 2022
|
|
* @author Andrey Gusakov <dron0gus@gmail.com>, (c) 2022
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
#if EFI_PROD_CODE
|
|
#if EFI_SENT_SUPPORT
|
|
|
|
#include "sent.h"
|
|
#include "init.h"
|
|
#include "sent_decoder.h"
|
|
|
|
#ifndef SENT_CHANNELS_NUM
|
|
#define SENT_CHANNELS_NUM 4 // Number of sent channels
|
|
#endif
|
|
|
|
static sent_channel channels[SENT_CHANNELS_NUM];
|
|
|
|
void sent_channel::Info() {
|
|
uint8_t stat;
|
|
uint16_t sig0, sig1;
|
|
|
|
efiPrintf("Unit time %lu timer ticks", tickPerUnit);
|
|
efiPrintf("Pause pulse detected %s", pausePulseReceived ? "Yes" : "No");
|
|
efiPrintf("Total pulses %lu", pulseCounter);
|
|
|
|
if (GetSignals(&stat, &sig0, &sig1) == 0) {
|
|
efiPrintf("Last valid fast msg Status 0x%01x Sig0 0x%03x Sig1 0x%03x", stat, sig0, sig1);
|
|
}
|
|
|
|
if (scMsgFlags) {
|
|
efiPrintf("Slow channels:");
|
|
for (int i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
|
|
if (scMsgFlags & BIT(i)) {
|
|
efiPrintf(" ID %d: %d", scMsg[i].id, scMsg[i].data);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if SENT_STATISTIC_COUNTERS
|
|
efiPrintf("HW overflows %lu\n", statistic.hwOverflowCnt);
|
|
|
|
efiPrintf("Pause pulses %lu\n", statistic.PauseCnt);
|
|
efiPrintf("Restarts %lu", statistic.RestartCnt);
|
|
efiPrintf("Interval errors %lu short, %lu long", statistic.ShortIntervalErr, statistic.LongIntervalErr);
|
|
efiPrintf("Total frames %lu with CRC error %lu (%f%%)", statistic.FrameCnt, statistic.CrcErrCnt, statistic.CrcErrCnt * 100.0 / statistic.FrameCnt);
|
|
efiPrintf("Total slow channel messages %lu with crc6 errors %lu (%f%%)", statistic.sc, statistic.scCrcErr, statistic.scCrcErr * 100.0 / statistic.sc);
|
|
efiPrintf("Sync errors %lu", statistic.SyncErr);
|
|
#endif
|
|
}
|
|
|
|
/*==========================================================================*/
|
|
/* Decoder thread settings. */
|
|
/*==========================================================================*/
|
|
|
|
/* 4 per channel should be enough */
|
|
#define SENT_MB_SIZE (4 * SENT_CHANNELS_NUM)
|
|
|
|
static msg_t sent_mb_buffer[SENT_MB_SIZE];
|
|
static MAILBOX_DECL(sent_mb, sent_mb_buffer, SENT_MB_SIZE);
|
|
|
|
static THD_WORKING_AREA(waSentDecoderThread, 256);
|
|
|
|
void SENT_ISR_Handler(uint8_t channel, uint16_t clocks, uint8_t flags) {
|
|
/* encode to fit msg_t */
|
|
msg_t msg = (flags << 24) | (channel << 16) | clocks;
|
|
|
|
/* called from ISR */
|
|
chSysLockFromISR();
|
|
chMBPostI(&sent_mb, msg);
|
|
chSysUnlockFromISR();
|
|
}
|
|
|
|
static void SentDecoderThread(void*) {
|
|
while (true) {
|
|
msg_t ret;
|
|
msg_t msg;
|
|
|
|
ret = chMBFetchTimeout(&sent_mb, &msg, TIME_INFINITE);
|
|
|
|
if (ret == MSG_OK) {
|
|
uint16_t tick = msg & 0xffff;
|
|
uint8_t n = (msg >> 16) & 0xff;
|
|
uint8_t flags = (msg >> 24) & 0xff;
|
|
|
|
if (n < SENT_CHANNELS_NUM) {
|
|
sent_channel &channel = channels[n];
|
|
|
|
if (channel.Decoder(tick, flags) > 0) {
|
|
/* report only for first channel */
|
|
if (n == 0) {
|
|
uint16_t sig0, sig1;
|
|
channel.GetSignals(NULL, &sig0, &sig1);
|
|
engine->sent_state.value0 = sig0;
|
|
engine->sent_state.value1 = sig1;
|
|
|
|
#if SENT_STATISTIC_COUNTERS
|
|
engine->sent_state.errorRate = 100.0 * channel.statistic.getErrorRate();
|
|
#endif // SENT_STATISTIC_COUNTERS
|
|
}
|
|
|
|
SentInput input = static_cast<SentInput>((size_t)SentInput::INPUT1 + n);
|
|
/* Call high level decoder from here */
|
|
/* TODO: implemnet subscribers, like it is done for ADC */
|
|
sentTpsDecode(input);
|
|
sentPressureDecode(input);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void printSentInfo() {
|
|
for (int i = 0; i < SENT_CHANNELS_NUM; i++) {
|
|
sent_channel &channel = channels[i];
|
|
|
|
const char * pinName = getBoardSpecificPinName(engineConfiguration->sentInputPins[i]);
|
|
efiPrintf("---- SENT input %d ---- on %s", i + 1, pinName);
|
|
channel.Info();
|
|
efiPrintf("--------------------");
|
|
}
|
|
}
|
|
|
|
/* Don't be confused: this actually returns throttle body position */
|
|
/* TODO: remove, replace with getSentValues() */
|
|
float getSentValue(SentInput input) {
|
|
size_t index = static_cast<size_t>(input) - static_cast<size_t>(SentInput::INPUT1);
|
|
|
|
if (index < SENT_CHANNELS_NUM) {
|
|
uint16_t sig0, sig1;
|
|
sent_channel &channel = channels[index];
|
|
|
|
if (channel.GetSignals(NULL, &sig0, &sig1) == 0) {
|
|
|
|
// GM sig0 + sig1 == 0xfff but Ford does not
|
|
/* scale to 0.0 .. 1.0 */
|
|
return sig0;
|
|
}
|
|
}
|
|
|
|
return NAN;
|
|
}
|
|
|
|
int getSentValues(SentInput input, uint16_t *sig0, uint16_t *sig1) {
|
|
size_t index = static_cast<size_t>(input) - static_cast<size_t>(SentInput::INPUT1);
|
|
|
|
if (index < SENT_CHANNELS_NUM) {
|
|
sent_channel &channel = channels[index];
|
|
|
|
return channel.GetSignals(NULL, sig0, sig1);
|
|
}
|
|
|
|
/* invalid channel */
|
|
return -1;
|
|
}
|
|
|
|
/* Should be called once */
|
|
void initSent(void) {
|
|
/* init interval mailbox */
|
|
chMBObjectInit(&sent_mb, sent_mb_buffer, SENT_MB_SIZE);
|
|
|
|
chThdCreateStatic(waSentDecoderThread, sizeof(waSentDecoderThread), NORMALPRIO, SentDecoderThread, nullptr);
|
|
|
|
/* Start HW layer */
|
|
startSent();
|
|
|
|
addConsoleAction("sentinfo", &printSentInfo);
|
|
}
|
|
|
|
#endif /* EFI_SENT_SUPPORT */
|
|
#endif /* EFI_PROD_CODE */
|