Implement TS tooth logger (#873)
* FW changes * config changes * whitespace * comment * simplify
This commit is contained in:
parent
1fce0201a5
commit
d708f3e038
|
@ -75,6 +75,7 @@
|
|||
#include "crc.h"
|
||||
#include "bluetooth.h"
|
||||
#include "tunerstudio_io.h"
|
||||
#include "tooth_logger.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "engine_configuration.h"
|
||||
|
@ -448,8 +449,10 @@ static bool isKnownCommand(char command) {
|
|||
|| command == TS_IO_TEST_COMMAND
|
||||
|| command == TS_GET_STRUCT
|
||||
|| command == TS_GET_FILE_RANGE
|
||||
|| command == TS_TOOTH_COMMAND
|
||||
|| command == TS_GET_TEXT || command == TS_CRC_CHECK_COMMAND
|
||||
|| command == TS_SET_LOGGER_MODE
|
||||
|| command == TS_GET_LOGGER_BUFFER
|
||||
|| command == TS_GET_TEXT
|
||||
|| command == TS_CRC_CHECK_COMMAND
|
||||
|| command == TS_GET_FIRMWARE_VERSION;
|
||||
}
|
||||
|
||||
|
@ -790,6 +793,29 @@ int tunerStudioHandleCrcCommand(ts_channel_s *tsChannel, char *data, int incomin
|
|||
#endif /* EFI_PROD_CODE */
|
||||
sendOkResponse(tsChannel, TS_CRC);
|
||||
}
|
||||
break;
|
||||
case TS_SET_LOGGER_MODE:
|
||||
switch(data[0]) {
|
||||
case 0x01:
|
||||
EnableToothLogger();
|
||||
break;
|
||||
case 0x02:
|
||||
DisableToothLogger();
|
||||
break;
|
||||
default:
|
||||
// dunno what that was, send NAK
|
||||
return false;
|
||||
}
|
||||
|
||||
sendOkResponse(tsChannel, TS_CRC);
|
||||
|
||||
break;
|
||||
case TS_GET_LOGGER_BUFFER:
|
||||
{
|
||||
auto toothBuffer = GetToothLoggerBuffer();
|
||||
sr5SendResponse(tsChannel, TS_CRC, toothBuffer.Buffer, toothBuffer.Length);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
tunerStudioError("ERROR: ignoring unexpected command");
|
||||
|
|
|
@ -68,7 +68,10 @@ typedef struct {
|
|||
#define TS_PAGE_COMMAND 'P' // 0x50
|
||||
#define TS_COMMAND_F 'F' // 0x46
|
||||
#define TS_GET_FIRMWARE_VERSION 'V' // versionInfo
|
||||
#define TS_TOOTH_COMMAND 'L' // 0x4C
|
||||
|
||||
// High speed logger commands
|
||||
#define TS_SET_LOGGER_MODE 'l'
|
||||
#define TS_GET_LOGGER_BUFFER 'L'
|
||||
|
||||
#define TS_SINGLE_WRITE_COMMAND 'W' // 0x57 pageValueWrite
|
||||
#define TS_CHUNK_WRITE_COMMAND 'C' // 0x43 pageChunkWrite
|
||||
|
|
|
@ -3,5 +3,6 @@ CONSOLESRC =
|
|||
|
||||
CONSOLE_SRC_CPP = $(PROJECT_DIR)/console/status_loop.cpp \
|
||||
$(PROJECT_DIR)/console/console_io.cpp \
|
||||
$(PROJECT_DIR)/console/eficonsole.cpp
|
||||
$(PROJECT_DIR)/console/eficonsole.cpp \
|
||||
$(PROJECT_DIR)/console/tooth_logger.cpp
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
#include "tooth_logger.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include "efitime.h"
|
||||
#include "global.h"
|
||||
#include "efilib.h"
|
||||
#include "tunerstudio_configuration.h"
|
||||
|
||||
extern TunerStudioOutputChannels tsOutputChannels;
|
||||
|
||||
static uint16_t buffer[1000] CCM_OPTIONAL;
|
||||
static size_t NextIdx = 0;
|
||||
static volatile bool ToothLoggerEnabled = false;
|
||||
|
||||
static uint32_t lastEdgeTimestamp = 0;
|
||||
|
||||
void SetNextEntry(uint16_t entry) {
|
||||
// TS uses big endian, grumble
|
||||
buffer[NextIdx] = SWAP_UINT16(entry);
|
||||
NextIdx++;
|
||||
|
||||
// If we hit the end, loop
|
||||
if (NextIdx >= sizeof(buffer) / sizeof(buffer[0])) {
|
||||
NextIdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LogTriggerTooth(trigger_event_e tooth) {
|
||||
// bail if we aren't enabled
|
||||
if (!ToothLoggerEnabled) return;
|
||||
|
||||
// We currently only support the primary trigger falling edge
|
||||
// (this is the edge that VR sensors are accurate on)
|
||||
// Since VR senors are the most useful case here, this is okay for now.
|
||||
if (tooth != SHAFT_PRIMARY_FALLING) return;
|
||||
|
||||
uint32_t nowUs = NT2US(getTimeNowNt());
|
||||
// 10us per LSB - this gives plenty of accuracy, yet fits 655.35 ms in to a uint16
|
||||
uint16_t delta = static_cast<uint16_t>((nowUs - lastEdgeTimestamp) / 10);
|
||||
lastEdgeTimestamp = nowUs;
|
||||
|
||||
SetNextEntry(delta);
|
||||
}
|
||||
|
||||
void EnableToothLogger() {
|
||||
// Clear the buffer
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
// Reset the last edge to now - this prevents the first edge logged from being bogus
|
||||
lastEdgeTimestamp = NT2US(getTimeNowNt());
|
||||
|
||||
// Reset write index
|
||||
NextIdx = 0;
|
||||
|
||||
// Enable logging of edges as they come
|
||||
ToothLoggerEnabled = true;
|
||||
|
||||
// Tell TS that we're ready for it to read out the log
|
||||
// nb: this is a lie, as we may not have written anything
|
||||
// yet. However, we can let it continuously read out the buffer
|
||||
// as we update it, which looks pretty nice.
|
||||
tsOutputChannels.toothLogReady = true;
|
||||
}
|
||||
|
||||
void DisableToothLogger() {
|
||||
ToothLoggerEnabled = false;
|
||||
tsOutputChannels.toothLogReady = false;
|
||||
}
|
||||
|
||||
ToothLoggerBuffer GetToothLoggerBuffer() {
|
||||
return { reinterpret_cast<uint8_t*>(buffer), sizeof(buffer) };
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include "rusefi_enums.h"
|
||||
|
||||
// Enable the tooth logger - this clears the buffer starts logging
|
||||
void EnableToothLogger();
|
||||
|
||||
// Stop logging - leave buffer intact
|
||||
void DisableToothLogger();
|
||||
|
||||
// A new tooth has arrived! Log to the buffer if enabled.
|
||||
void LogTriggerTooth(trigger_event_e tooth);
|
||||
|
||||
struct ToothLoggerBuffer
|
||||
{
|
||||
const uint8_t* const Buffer;
|
||||
const size_t Length;
|
||||
};
|
||||
|
||||
// Get a reference to the buffer
|
||||
ToothLoggerBuffer GetToothLoggerBuffer();
|
|
@ -17,6 +17,7 @@
|
|||
#include "data_buffer.h"
|
||||
#include "histogram.h"
|
||||
#include "pwm_generator_logic.h"
|
||||
#include "tooth_logger.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "engine_math.h"
|
||||
|
@ -190,6 +191,11 @@ static bool isInsideTriggerHandler = false;
|
|||
|
||||
|
||||
void hwHandleShaftSignal(trigger_event_e signal) {
|
||||
// Log to the Tunerstudio tooth logger
|
||||
// We want to do this before anything else as we
|
||||
// actually want to capture any noise/jitter that may be occuring
|
||||
LogTriggerTooth(signal);
|
||||
|
||||
// for effective noise filtering, we need both signal edges,
|
||||
// so we pass them to handleShaftSignal() and defer this test
|
||||
if (!CONFIGB(useNoiselessTriggerDecoder)) {
|
||||
|
|
|
@ -104,22 +104,20 @@ enable2ndByteCanID = false
|
|||
|
||||
|
||||
[LoggerDefinition]
|
||||
|
||||
; valid logger types: composite, tooth, trigger, csv
|
||||
loggerDef = tooth, "Tooth Logger", tooth
|
||||
dataReadCommand = "L"
|
||||
dataReadTimeout = 15000 ; time in ms
|
||||
dataReadyCondition = { toothLogReady }
|
||||
dataLength = 256 ; in bytes, including headers, footers and data
|
||||
loggerDef = compositeLogger, "Primary Trigger Logger", tooth
|
||||
startCommand = "l\x01"
|
||||
stopCommand = "l\x02"
|
||||
dataReadCommand = "L"
|
||||
dataReadTimeout = 10000 ; time in ms
|
||||
dataReadyCondition = { toothLogReady }
|
||||
|
||||
; recordDef = headerLen, footerLen, recordLen
|
||||
recordDef = 0, 0, 4; in bytes, the recordLen is for each record, currently limited to 4 bytes
|
||||
recordDef = 0, 0, 2; in bytes, the recordLen is for each record, currently limited to 4 bytes
|
||||
|
||||
; uint16 that stores 1/100 second
|
||||
recordField = toothTime, "tooth", 0, 16, 0.01, "ms"
|
||||
|
||||
recordField = PA3, "Inj D", 3, 1, 1, ""
|
||||
recordField = PA2, "Inj C", 2, 1, 1, ""
|
||||
recordField = PA1, "Inj B", 1, 1, 1, ""
|
||||
recordField = PA0, "Inj A", 0, 1, 1, ""
|
||||
|
||||
[VeAnalyze]
|
||||
|
||||
|
|
Loading…
Reference in New Issue