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);
376 int totalResponseSize = 0;
377 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
379 uint16_t type = packed >> 13;
381 size_t size = type == 0 ? 0 : 1 << (type - 1);
385 totalResponseSize +=
size;
394 uint8_t dataBuffer[8];
395 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
397 uint16_t type = packed >> 13;
398 uint16_t
offset = packed & 0x1FFF;
402 size_t size = 1 << (type - 1);
406 tsChannel->
write(dataBuffer,
size,
false);
407 crc = crc32inc((
void*)dataBuffer, crc,
size);
414 tsChannel->
write(dataBuffer, 4,
true);
421 efiPrintf(
"TS <- Page %d read chunk offset %d count %d",
page,
offset,
count);
430 if (
page == TS_PAGE_SETTINGS) {
438 if (
addr ==
nullptr) {
439 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: RD invalid page");
444#if EFI_TUNER_STUDIO_VERBOSE
454#if EFI_CONFIGURATION_STORAGE
465 if (
page == TS_PAGE_SETTINGS) {
471 efiPrintf(
"TS -> Burn");
480 efiPrintf(
"TS -> Burn, we are allowed to burn");
483 efiPrintf(
"Burned in %.1fms", t.getElapsedSeconds() * 1e3);
485 }
else if (
page == TS_PAGE_SCATTER_OFFSETS) {
489 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: Burn invalid page");
496#if (EFI_PROD_CODE || EFI_SIMULATOR)
499 return command == TS_HELLO_COMMAND || command == TS_READ_COMMAND || command == TS_OUTPUT_COMMAND
500 || command == TS_BURN_COMMAND
501 || command == TS_CHUNK_WRITE_COMMAND || command == TS_EXECUTE
502 || command == TS_IO_TEST_COMMAND
504 || command == TS_SIMULATE_CAN
507 || command == TS_GET_SCATTERED_GET_COMMAND
509 || command == TS_SET_LOGGER_SWITCH
510 || command == TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY
511 || command == TS_GET_TEXT
512 || command == TS_CRC_CHECK_COMMAND
513 || command == TS_GET_FIRMWARE_VERSION
514 || command == TS_PERF_TRACE_BEGIN
515 || command == TS_PERF_TRACE_GET_BUFFER
516 || command == TS_GET_CONFIG_ERROR
517 || command == TS_QUERY_BOOTLOADER;
525 char testOutputBuffer[64];
531 tsChannel->
write((
const uint8_t*)QUOTE(SIGNATURE_HASH),
sizeof(QUOTE(SIGNATURE_HASH)));
534 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
536 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer),
" uptime=%ds ", (
int)
getTimeNowS());
537 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
539 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer), __DATE__
" %s\r\n", PROTOCOL_TEST_RESPONSE_TAG);
540 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
542 if (hasFirmwareError()) {
544 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer),
"error=%s\r\n", error);
545 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
552 if (strlen(errorMessage) == 0) {
556 tsChannel->
sendResponse(
TS_CRC,
reinterpret_cast<const uint8_t*
>(errorMessage), strlen(errorMessage),
true);
569 efiPrintf(
"TS <- Query signature: %s", signature);
570 tsChannel->
sendResponse(mode, (
const uint8_t *)signature, strlen(signature) + 1);
582 }
else if (command == TS_HELLO_COMMAND || command == TS_QUERY_COMMAND) {
584 efiPrintf(
"Got naked Query command");
587 }
else if (command == TS_TEST_COMMAND || command ==
'T') {
590 }
else if (command == TS_COMMAND_F) {
600 tsChannel->
write((
const uint8_t *)TS_PROTOCOL, strlen(TS_PROTOCOL));
615 chThdSleepMilliseconds(10);
622 size_t received = tsChannel->
readTimeout(&firstByte, 1, TS_COMMUNICATION_TIMEOUT);
624 logMsg(
"received %d\r\n", received);
629#if EFI_BLUETOOTH_SETUP
646 received = tsChannel->
readTimeout(&secondByte, 1, TS_COMMUNICATION_TIMEOUT_SHORT);
653 uint16_t incomingPacketSize = firstByte << 8 | secondByte;
654 size_t expectedSize = incomingPacketSize + TS_PACKET_TAIL_SIZE;
656 if ((incomingPacketSize == 0) || (expectedSize >
sizeof(tsChannel->
scratchBuffer))) {
658 efiPrintf(
"process_ts: channel=%s invalid size: %d", tsChannel->
name, incomingPacketSize);
661 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"invalid size");
674 if (received != expectedSize) {
676 efiPrintf(
"Got only %d bytes while expecting %d for command 0x%02x", received,
677 expectedSize, command);
687 efiPrintf(
"unexpected command %x", command);
688 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"unknown");
702 received = tsChannel->
readTimeout((uint8_t*)(tsChannel->
scratchBuffer) + 1, expectedSize - 1, TS_COMMUNICATION_TIMEOUT);
703 if (received != expectedSize - 1) {
710 logMsg(
"command %c\r\n", command);
713 uint32_t expectedCrc = *(uint32_t*) (tsChannel->
scratchBuffer + incomingPacketSize);
717 uint32_t actualCrc = crc32(tsChannel->
scratchBuffer, incomingPacketSize);
718 if (actualCrc != expectedCrc) {
721 efiPrintf(
"TunerStudio: command %c actual CRC %x/expected %x", tsChannel->
scratchBuffer[0],
722 (
unsigned int)actualCrc, (
unsigned int)expectedCrc);
724 sendErrorCode(tsChannel, TS_RESPONSE_CRC_FAILURE,
"crc_issue");
736 efiPrintf(
"got unexpected TunerStudio command %x:%c", command, command);
770#if EFI_PROD_CODE || EFI_SIMULATOR
777 char versionBuffer[32];
778 chsnprintf(versionBuffer,
sizeof(versionBuffer),
"%s v%d@%u", FRONTEND_TITLE_BAR_NAME,
getRusEfiVersion(), SIGNATURE_HASH);
779 tsChannel->
sendResponse(
TS_CRC, (
const uint8_t *) versionBuffer, strlen(versionBuffer) + 1);
791 logMsg(
"get test sending [%d]\r\n", outputSize);
794 tsChannel->
writeCrcPacket(TS_RESPONSE_OK,
reinterpret_cast<const uint8_t*
>(output), outputSize,
true);
796 logMsg(
"sent [%d]\r\n", outputSize);
802 data[incomingPacketSize] = 0;
805 logMsg(
"execute [%s]\r\n", trimmed);
815 char command = data[0];
818 const uint16_t* data16 =
reinterpret_cast<uint16_t*
>(data);
827 if (incomingPacketSize >= 3) {
831 if (incomingPacketSize >= 5) {
837 case TS_OUTPUT_COMMAND:
838 if (incomingPacketSize == 1) {
840 count = TS_TOTAL_OUTPUT_SIZE;
844 case TS_OUTPUT_ALL_COMMAND:
846 count = TS_TOTAL_OUTPUT_SIZE;
850 case TS_GET_SCATTERED_GET_COMMAND:
854 criticalError(
"Slow/wireless mode not supported");
857 case TS_HELLO_COMMAND:
861 case TS_GET_FIRMWARE_VERSION:
872 case TS_CHUNK_WRITE_COMMAND:
879 case TS_CRC_CHECK_COMMAND:
886 case TS_BURN_COMMAND:
891 case TS_READ_COMMAND:
898 case TS_TEST_COMMAND:
903 case TS_GET_CONFIG_ERROR:
907 case TS_SIMULATE_CAN:
908 void handleWrapCan(
TsChannelBase* tsChannel,
char *data,
int incomingPacketSize);
909 handleWrapCan(tsChannel, data, incomingPacketSize - 1);
912 case TS_IO_TEST_COMMAND:
913#if EFI_SIMULATOR || EFI_PROD_CODE
927 case TS_SET_LOGGER_SWITCH:
929 case TS_COMPOSITE_ENABLE:
932 case TS_COMPOSITE_DISABLE:
935 case TS_COMPOSITE_READ:
945 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
950 case TS_TRIGGER_SCOPE_ENABLE:
953 case TS_TRIGGER_SCOPE_DISABLE:
956 case TS_TRIGGER_SCOPE_READ:
964 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
977 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
989 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
995 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
996 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
1000 case TS_PERF_TRACE_BEGIN:
1004 case TS_PERF_TRACE_GET_BUFFER:
1012 case TS_PERF_TRACE_BEGIN:
1013 criticalError(
"TS_PERF_TRACE not supported");
1015 case TS_PERF_TRACE_GET_BUFFER:
1016 criticalError(
"TS_PERF_TRACE_GET_BUFFER not supported");
1019 case TS_QUERY_BOOTLOADER: {
1020 uint8_t bldata = TS_QUERY_BOOTLOADER_NONE;
1022 bldata = TS_QUERY_BOOTLOADER_OPENBLT;
1029 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"unknown_command");
1030static char tsErrorBuff[80];
1031 chsnprintf(tsErrorBuff,
sizeof(tsErrorBuff),
"ERROR: ignoring unexpected command %d [%c]", command, command);
1043 return !calibrationsVeWriteTimer.hasElapsedSec(tuningDetector);
1048 static_assert(
sizeof(
persistent_config_s) == TOTAL_CONFIG_SIZE,
"TS datapage size mismatch");
1060#if EFI_BLUETOOTH_SETUP
1065 addConsoleActionSSS(
"bluetooth_hc05", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1068 addConsoleActionSSS(
"bluetooth_hc06", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1071 addConsoleActionSSS(
"bluetooth_bk", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1074 addConsoleActionSSS(
"bluetooth_jdy", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1077 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
static void onConfigOnStartUpOrBurn(bool isRunningOnBurn)
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()