89#include "rusEfiFunctionalTest.h"
97static_assert(
sizeof(*config) <= 65536);
100 efiPrintf(
"TunerStudio size=%d / total=%d / errors=%d / H=%d / O=%d / P=%d / B=%d / 9=%d",
104 efiPrintf(
"TunerStudio C=%d",
106 efiPrintf(
"TunerStudio errors: underrun=%d / overrun=%d / crc=%d / unrecognized=%d / outofrange=%d / other=%d",
112 Timer calibrationsVeWriteTimer;
117 efiPrintf(
"Scatter list (global)");
118 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
119 uint16_t packed = tsChannel->highSpeedOffsets[i];
120 uint16_t type = packed >> 13;
121 uint16_t
offset = packed & 0x1FFF;
125 size_t size = 1 << (type - 1);
127 efiPrintf(
"%02d offset 0x%04x size %d", i,
offset,
size);
133#define TS_COMMUNICATION_TIMEOUT TIME_MS2I(1000)
135#define TS_COMMUNICATION_TIMEOUT_SHORT TIME_MS2I(10)
142#ifdef EFI_CONSOLE_RX_BRAIN_PIN
143 efiPrintf(
"Primary UART RX %s",
hwPortname(EFI_CONSOLE_RX_BRAIN_PIN));
144 efiPrintf(
"Primary UART TX %s",
hwPortname(EFI_CONSOLE_TX_BRAIN_PIN));
163#if EFI_TUNER_STUDIO_VERBOSE
164 efiPrintf(
"%s: %s", tsChannel->
name, msg);
171 case TS_PAGE_SETTINGS:
176 case TS_PAGE_SCATTER_OFFSETS:
180 case TS_PAGE_LTFT_TRIMS:
192 case TS_PAGE_SETTINGS:
193 return TOTAL_CONFIG_SIZE;
195 case TS_PAGE_SCATTER_OFFSETS:
199 case TS_PAGE_LTFT_TRIMS:
212 efiPrintf(
"TS: Project mismatch? Too much configuration requested %d+%d>%d",
offset,
count, allowedSize);
214 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"bad_offset");
233 case TS_RESPONSE_UNDERRUN:
236 case TS_RESPONSE_OVERRUN:
239 case TS_RESPONSE_CRC_FAILURE:
242 case TS_RESPONSE_UNRECOGNIZED_COMMAND:
245 case TS_RESPONSE_OUT_OF_RANGE:
278 calibrationsVeWriteTimer.reset();
287 if (
offset > areaStart + areaSize) {
302 efiPrintf(
"TS -> Page %d write chunk offset %d count %d (output_count=%d)",
313 if (
addr ==
nullptr) {
314 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: WR invalid page");
321 if (
page == TS_PAGE_SETTINGS) {
323 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"locked");
332 efiPrintf(
"Ignoring TS -> Page %d write chunk offset %d count %d (output_count=%d)",
360 if (start ==
nullptr) {
361 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: CRC invalid page");
367 efiPrintf(
"TS <- Get CRC page %d offset %d count %d result %08x",
page,
offset,
count, (
unsigned int)crc);
374 int totalResponseSize = 0;
375 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
377 uint16_t type = packed >> 13;
379 size_t size = type == 0 ? 0 : 1 << (type - 1);
383 totalResponseSize +=
size;
392 uint8_t dataBuffer[8];
393 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
395 uint16_t type = packed >> 13;
396 uint16_t
offset = packed & 0x1FFF;
400 size_t size = 1 << (type - 1);
404 tsChannel->
write(dataBuffer,
size,
false);
405 crc = crc32inc((
void*)dataBuffer, crc,
size);
412 tsChannel->
write(dataBuffer, 4,
true);
419 efiPrintf(
"TS <- Page %d read chunk offset %d count %d",
page,
offset,
count);
428 if (
page == TS_PAGE_SETTINGS) {
436 if (
addr ==
nullptr) {
437 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: RD invalid page");
442#if EFI_TUNER_STUDIO_VERBOSE
452#if EFI_CONFIGURATION_STORAGE
463 if (
page == TS_PAGE_SETTINGS) {
469 efiPrintf(
"TS -> Burn");
480 efiPrintf(
"Burned in %.1fms", t.getElapsedSeconds() * 1e3);
482 }
else if (
page == TS_PAGE_SCATTER_OFFSETS) {
486 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: Burn invalid page");
493#if (EFI_PROD_CODE || EFI_SIMULATOR)
496 return command == TS_HELLO_COMMAND || command == TS_READ_COMMAND || command == TS_OUTPUT_COMMAND
497 || command == TS_BURN_COMMAND
498 || command == TS_CHUNK_WRITE_COMMAND || command == TS_EXECUTE
499 || command == TS_IO_TEST_COMMAND
501 || command == TS_SIMULATE_CAN
504 || command == TS_GET_SCATTERED_GET_COMMAND
506 || command == TS_SET_LOGGER_SWITCH
507 || command == TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY
508 || command == TS_GET_TEXT
509 || command == TS_CRC_CHECK_COMMAND
510 || command == TS_GET_FIRMWARE_VERSION
511 || command == TS_PERF_TRACE_BEGIN
512 || command == TS_PERF_TRACE_GET_BUFFER
513 || command == TS_GET_CONFIG_ERROR
514 || command == TS_QUERY_BOOTLOADER;
522 char testOutputBuffer[64];
528 tsChannel->
write((
const uint8_t*)QUOTE(SIGNATURE_HASH),
sizeof(QUOTE(SIGNATURE_HASH)));
531 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
533 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer),
" uptime=%ds ", (
int)
getTimeNowS());
534 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
536 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer), __DATE__
" %s\r\n", PROTOCOL_TEST_RESPONSE_TAG);
537 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
539 if (hasFirmwareError()) {
541 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer),
"error=%s\r\n", error);
542 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
549 if (strlen(errorMessage) == 0) {
553 tsChannel->
sendResponse(
TS_CRC,
reinterpret_cast<const uint8_t*
>(errorMessage), strlen(errorMessage),
true);
566 efiPrintf(
"TS <- Query signature: %s", signature);
567 tsChannel->
sendResponse(mode, (
const uint8_t *)signature, strlen(signature) + 1);
579 }
else if (command == TS_HELLO_COMMAND || command == TS_QUERY_COMMAND) {
581 efiPrintf(
"Got naked Query command");
584 }
else if (command == TS_TEST_COMMAND || command ==
'T') {
587 }
else if (command == TS_COMMAND_F) {
597 tsChannel->
write((
const uint8_t *)TS_PROTOCOL, strlen(TS_PROTOCOL));
612 chThdSleepMilliseconds(10);
619 size_t received = tsChannel->
readTimeout(&firstByte, 1, TS_COMMUNICATION_TIMEOUT);
621 logMsg(
"received %d\r\n", received);
626#if EFI_BLUETOOTH_SETUP
643 received = tsChannel->
readTimeout(&secondByte, 1, TS_COMMUNICATION_TIMEOUT_SHORT);
650 uint16_t incomingPacketSize = firstByte << 8 | secondByte;
651 size_t expectedSize = incomingPacketSize + TS_PACKET_TAIL_SIZE;
653 if ((incomingPacketSize == 0) || (expectedSize >
sizeof(tsChannel->
scratchBuffer))) {
655 efiPrintf(
"process_ts: channel=%s invalid size: %d", tsChannel->
name, incomingPacketSize);
658 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"invalid size");
671 if (received != expectedSize) {
673 efiPrintf(
"Got only %d bytes while expecting %d for command 0x%02x", received,
674 expectedSize, command);
684 efiPrintf(
"unexpected command %x", command);
685 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"unknown");
699 received = tsChannel->
readTimeout((uint8_t*)(tsChannel->
scratchBuffer) + 1, expectedSize - 1, TS_COMMUNICATION_TIMEOUT);
700 if (received != expectedSize - 1) {
707 logMsg(
"command %c\r\n", command);
710 uint32_t expectedCrc = *(uint32_t*) (tsChannel->
scratchBuffer + incomingPacketSize);
714 uint32_t actualCrc = crc32(tsChannel->
scratchBuffer, incomingPacketSize);
715 if (actualCrc != expectedCrc) {
718 efiPrintf(
"TunerStudio: command %c actual CRC %x/expected %x", tsChannel->
scratchBuffer[0],
719 (
unsigned int)actualCrc, (
unsigned int)expectedCrc);
721 sendErrorCode(tsChannel, TS_RESPONSE_CRC_FAILURE,
"crc_issue");
733 efiPrintf(
"got unexpected TunerStudio command %x:%c", command, command);
767#if EFI_PROD_CODE || EFI_SIMULATOR
774 char versionBuffer[32];
775 chsnprintf(versionBuffer,
sizeof(versionBuffer),
"%s v%d@%u", FRONTEND_TITLE_BAR_NAME,
getRusEfiVersion(), SIGNATURE_HASH);
776 tsChannel->
sendResponse(
TS_CRC, (
const uint8_t *) versionBuffer, strlen(versionBuffer) + 1);
788 logMsg(
"get test sending [%d]\r\n", outputSize);
791 tsChannel->
writeCrcPacket(TS_RESPONSE_OK,
reinterpret_cast<const uint8_t*
>(output), outputSize,
true);
793 logMsg(
"sent [%d]\r\n", outputSize);
799 data[incomingPacketSize] = 0;
802 logMsg(
"execute [%s]\r\n", trimmed);
812 char command = data[0];
815 const uint16_t* data16 =
reinterpret_cast<uint16_t*
>(data);
824 if (incomingPacketSize >= 3) {
828 if (incomingPacketSize >= 5) {
834 case TS_OUTPUT_COMMAND:
835 if (incomingPacketSize == 1) {
837 count = TS_TOTAL_OUTPUT_SIZE;
841 case TS_OUTPUT_ALL_COMMAND:
843 count = TS_TOTAL_OUTPUT_SIZE;
847 case TS_GET_SCATTERED_GET_COMMAND:
851 criticalError(
"Slow/wireless mode not supported");
854 case TS_HELLO_COMMAND:
858 case TS_GET_FIRMWARE_VERSION:
869 case TS_CHUNK_WRITE_COMMAND:
876 case TS_CRC_CHECK_COMMAND:
883 case TS_BURN_COMMAND:
888 case TS_READ_COMMAND:
895 case TS_TEST_COMMAND:
900 case TS_GET_CONFIG_ERROR:
904 case TS_SIMULATE_CAN:
905 void handleWrapCan(
TsChannelBase* tsChannel,
char *data,
int incomingPacketSize);
906 handleWrapCan(tsChannel, data, incomingPacketSize - 1);
909 case TS_IO_TEST_COMMAND:
910#if EFI_SIMULATOR || EFI_PROD_CODE
924 case TS_SET_LOGGER_SWITCH:
926 case TS_COMPOSITE_ENABLE:
929 case TS_COMPOSITE_DISABLE:
932 case TS_COMPOSITE_READ:
942 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
947 case TS_TRIGGER_SCOPE_ENABLE:
950 case TS_TRIGGER_SCOPE_DISABLE:
953 case TS_TRIGGER_SCOPE_READ:
961 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
974 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
986 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
992 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
993 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
997 case TS_PERF_TRACE_BEGIN:
1001 case TS_PERF_TRACE_GET_BUFFER:
1009 case TS_PERF_TRACE_BEGIN:
1010 criticalError(
"TS_PERF_TRACE not supported");
1012 case TS_PERF_TRACE_GET_BUFFER:
1013 criticalError(
"TS_PERF_TRACE_GET_BUFFER not supported");
1016 case TS_QUERY_BOOTLOADER: {
1017 uint8_t bldata = TS_QUERY_BOOTLOADER_NONE;
1019 bldata = TS_QUERY_BOOTLOADER_OPENBLT;
1026 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"unknown_command");
1027static char tsErrorBuff[80];
1028 chsnprintf(tsErrorBuff,
sizeof(tsErrorBuff),
"ERROR: ignoring unexpected command %d [%c]", command, command);
1040 return !calibrationsVeWriteTimer.hasElapsedSec(tuningDetector);
1045 static_assert(
sizeof(
persistent_config_s) == TOTAL_CONFIG_SIZE,
"TS datapage size mismatch");
1057#if EFI_BLUETOOTH_SETUP
1062 addConsoleActionSSS(
"bluetooth_hc05", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1065 addConsoleActionSSS(
"bluetooth_hc06", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1068 addConsoleActionSSS(
"bluetooth_bk", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1071 addConsoleActionSSS(
"bluetooth_jdy", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1074 addConsoleActionSSS(
"bluetooth_jdy31", [](
const char *baudRate,
const char *name,
const char *pinCode) {
void executeTSCommand(uint16_t subsystem, uint16_t index)
Utility methods related to bench testing.
void bluetoothSoftwareDisconnectNotify(SerialTsChannelBase *tsChannel)
void bluetoothStart(bluetooth_module_e moduleType, const char *baudRate, const char *name, const char *pinCode)
static bool call_board_override(std::optional< FuncType > board_override, Args &&... args)
const TBuffer * get() const
Timer engineTypeChangeTimer
TunerStudioOutputChannels outputChannels
WarningCodeState warnings
virtual bool isReady() const
char scratchBuffer[scratchBuffer_SIZE+30]
uint32_t writePacketHeader(const uint8_t responseCode, const size_t size)
void writeCrcResponse(uint8_t responseCode)
virtual void writeCrcPacket(uint8_t responseCode, const uint8_t *buf, size_t size, bool allowLongPackets=false)
virtual void write(const uint8_t *buffer, size_t size, bool isEndOfPacket=false)=0
virtual size_t readTimeout(uint8_t *buffer, size_t size, int timeout)=0
void sendResponse(ts_response_format_e mode, const uint8_t *buffer, int size, bool allowLongPackets=false)
void sendErrorCode(TsChannelBase *tsChannel, uint8_t code, const char *msg="")
void handleScatteredReadCommand(TsChannelBase *tsChannel)
bool handlePlainCommand(TsChannelBase *tsChannel, uint8_t command)
void handleCrc32Check(TsChannelBase *tsChannel, uint16_t page, uint16_t offset, uint16_t count)
void handleQueryCommand(TsChannelBase *tsChannel, ts_response_format_e mode)
void cmdOutputChannels(TsChannelBase *tsChannel, uint16_t offset, uint16_t count) override
'Output' command sends out a snapshot of current values Gauges refresh
void handlePageReadCommand(TsChannelBase *tsChannel, uint16_t page, uint16_t offset, uint16_t count)
void handleWriteChunkCommand(TsChannelBase *tsChannel, uint16_t page, uint16_t offset, uint16_t count, void *content)
int handleCrcCommand(TsChannelBase *tsChannel, char *data, int incomingPacketSize)
void handleExecuteCommand(TsChannelBase *tsChannel, char *data, int incomingPacketSize)
virtual TsChannelBase * setupChannel()=0
void ThreadTask() override
const char * getWarningMessage()
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback)
void addConsoleActionI(const char *token, VoidInt callback)
Register a console command with one Integer parameter.
void onDataArrived(bool valid)
void(* CommandHandler)(char *)
void printUsbConnectorStats()
char * efiTrim(char *param)
uint32_t SWAP_UINT32(uint32_t x)
uint16_t SWAP_UINT16(uint16_t x)
efitimesec_t getTimeNowS()
Current system time in seconds (32 bits)
static EngineAccessor engine
std::optional< setup_custom_board_overrides_type > custom_board_ConfigOverrides
static constexpr persistent_config_s * config
static constexpr engine_configuration_s * engineConfiguration
bool validateConfigOnStartUpOrBurn()
const char * getCriticalErrorMessage()
const char * getConfigErrorMessage()
void setNeedToWriteConfiguration()
UNUSED(samplingTimeSeconds)
FragmentList getLiveDataFragments()
const char * swapOutputBuffers(size_t *actualOutputBufferSize)
size_t ltftGetTsPageSize()
This data structure holds current malfunction codes.
@ STACK_USAGE_COMMUNICATION
const BigBufferHandle perfTraceGetBuffer()
@ TunerStudioHandleCrcCommand
const char * hwPortname(brain_pin_e brainPin)
const char * getTsSignature()
void printOverallStatus()
uint32_t tunerStudioSerialSpeed
bool isTuningDetectorEnabled
uint16_t highSpeedOffsets[TS_SCATTER_OFFSETS_COUNT]
scaled_channel< uint16_t, 10, 1 > veTable[VE_LOAD_COUNT][VE_RPM_COUNT]
int readPageCommandsCounter
int errorUnrecognizedCommand
int readScatterCommandsCounter
int outputChannelsCommandCounter
int crc32CheckCommandCounter
int writeChunkCommandCounter
void DisableToothLogger()
CompositeBuffer * GetToothLoggerBufferNonblocking()
void ReturnToothLoggerBuffer(CompositeBuffer *buffer)
void EnableToothLoggerIfNotEnabled()
void triggerScopeEnable()
const BigBufferHandle & triggerScopeGetBuffer()
static BigBufferHandle buffer
void triggerScopeDisable()
bool isTouchingArea(uint16_t offset, uint16_t count, int areaStart, int areaSize)
static bool isKnownCommand(char command)
bool needToTriggerTsRefresh()
static void onCalibrationWrite(uint16_t page, uint16_t offset, uint16_t count)
static constexpr size_t getTunerStudioPageSize(size_t page)
static void handleGetVersion(TsChannelBase *tsChannel)
tunerstudio_counters_s tsState
PUBLIC_API_WEAK bool isBoardAskingTriggerTsRefresh()
static void printScatterList(TsChannelBase *tsChannel)
static void handleGetConfigErorr(TsChannelBase *tsChannel)
static void setTsSpeed(int value)
CommandHandler console_line_callback
void sendErrorCode(TsChannelBase *tsChannel, uint8_t code, const char *msg)
PUBLIC_API_WEAK bool isTouchingVe(uint16_t offset, uint16_t count)
static void handleGetText(TsChannelBase *tsChannel)
static uint8_t * getWorkingPageAddr(TsChannelBase *tsChannel, size_t page, size_t offset)
void startTunerStudioConnectivity()
static bool validateOffsetCount(size_t page, size_t offset, size_t count, TsChannelBase *tsChannel)
static void sendOkResponse(TsChannelBase *tsChannel)
static void handleTestCommand(TsChannelBase *tsChannel)
static int tsProcessOne(TsChannelBase *tsChannel)
void tunerStudioDebug(TsChannelBase *tsChannel, const char *msg)
static void printErrorCounters()
static void printTsStats(void)
static void handleBurnCommand(TsChannelBase *tsChannel, uint16_t page)
void tunerStudioError(TsChannelBase *tsChannel, const char *msg)
SerialTsChannelBase * getBluetoothChannel()