90#include "rusEfiFunctionalTest.h"
98static_assert(
sizeof(*config) <= 65536);
101 efiPrintf(
"TunerStudio size=%d / total=%d / errors=%d / H=%d / O=%d / P=%d / B=%d / 9=%d",
105 efiPrintf(
"TunerStudio C=%d",
107 efiPrintf(
"TunerStudio errors: underrun=%d / overrun=%d / crc=%d / unrecognized=%d / outofrange=%d / other=%d",
113 Timer calibrationsVeWriteTimer;
118 efiPrintf(
"Scatter list (global)");
119 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
120 uint16_t packed = tsChannel->highSpeedOffsets[i];
121 uint16_t type = packed >> 13;
122 uint16_t
offset = packed & 0x1FFF;
126 size_t size = 1 << (type - 1);
128 efiPrintf(
"%02d offset 0x%04x size %d", i,
offset,
size);
134#define TS_COMMUNICATION_TIMEOUT TIME_MS2I(1000)
136#define TS_COMMUNICATION_TIMEOUT_SHORT TIME_MS2I(10)
143#ifdef EFI_CONSOLE_RX_BRAIN_PIN
144 efiPrintf(
"Primary UART RX %s",
hwPortname(EFI_CONSOLE_RX_BRAIN_PIN));
145 efiPrintf(
"Primary UART TX %s",
hwPortname(EFI_CONSOLE_TX_BRAIN_PIN));
164#if EFI_TUNER_STUDIO_VERBOSE
165 efiPrintf(
"%s: %s", tsChannel->
name, msg);
172 case TS_PAGE_SETTINGS:
177 case TS_PAGE_SCATTER_OFFSETS:
181 case TS_PAGE_LTFT_TRIMS:
193 case TS_PAGE_SETTINGS:
194 return TOTAL_CONFIG_SIZE;
196 case TS_PAGE_SCATTER_OFFSETS:
200 case TS_PAGE_LTFT_TRIMS:
213 efiPrintf(
"TS: Project mismatch? Too much configuration requested %d+%d>%d",
offset,
count, allowedSize);
215 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"bad_offset");
234 case TS_RESPONSE_UNDERRUN:
237 case TS_RESPONSE_OVERRUN:
240 case TS_RESPONSE_CRC_FAILURE:
243 case TS_RESPONSE_UNRECOGNIZED_COMMAND:
246 case TS_RESPONSE_OUT_OF_RANGE:
279 calibrationsVeWriteTimer.reset();
288 if (
offset > areaStart + areaSize) {
303 efiPrintf(
"TS -> Page %d write chunk offset %d count %d (output_count=%d)",
314 if (
addr ==
nullptr) {
315 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: WR invalid page");
322 if (
page == TS_PAGE_SETTINGS) {
324 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"locked");
333 efiPrintf(
"Ignoring TS -> Page %d write chunk offset %d count %d (output_count=%d)",
361 if (start ==
nullptr) {
362 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: CRC invalid page");
368 efiPrintf(
"TS <- Get CRC page %d offset %d count %d result %08x",
page,
offset,
count, (
unsigned int)crc);
375 int totalResponseSize = 0;
376 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
378 uint16_t type = packed >> 13;
380 size_t size = type == 0 ? 0 : 1 << (type - 1);
384 totalResponseSize +=
size;
393 uint8_t dataBuffer[8];
394 for (
size_t i = 0; i < TS_SCATTER_OFFSETS_COUNT; i++) {
396 uint16_t type = packed >> 13;
397 uint16_t
offset = packed & 0x1FFF;
401 size_t size = 1 << (type - 1);
405 tsChannel->
write(dataBuffer,
size,
false);
406 crc = crc32inc((
void*)dataBuffer, crc,
size);
413 tsChannel->
write(dataBuffer, 4,
true);
420 efiPrintf(
"TS <- Page %d read chunk offset %d count %d",
page,
offset,
count);
429 if (
page == TS_PAGE_SETTINGS) {
437 if (
addr ==
nullptr) {
438 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: RD invalid page");
443#if EFI_TUNER_STUDIO_VERBOSE
453#if EFI_CONFIGURATION_STORAGE
464 if (
page == TS_PAGE_SETTINGS) {
470 efiPrintf(
"TS -> Burn");
481 efiPrintf(
"Burned in %.1fms", t.getElapsedSeconds() * 1e3);
483 }
else if (
page == TS_PAGE_SCATTER_OFFSETS) {
487 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"ERROR: Burn invalid page");
494#if (EFI_PROD_CODE || EFI_SIMULATOR)
497 return command == TS_HELLO_COMMAND || command == TS_READ_COMMAND || command == TS_OUTPUT_COMMAND
498 || command == TS_BURN_COMMAND
499 || command == TS_CHUNK_WRITE_COMMAND || command == TS_EXECUTE
500 || command == TS_IO_TEST_COMMAND
502 || command == TS_SIMULATE_CAN
505 || command == TS_GET_SCATTERED_GET_COMMAND
507 || command == TS_SET_LOGGER_SWITCH
508 || command == TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY
509 || command == TS_GET_TEXT
510 || command == TS_CRC_CHECK_COMMAND
511 || command == TS_GET_FIRMWARE_VERSION
512 || command == TS_PERF_TRACE_BEGIN
513 || command == TS_PERF_TRACE_GET_BUFFER
514 || command == TS_GET_CONFIG_ERROR
515 || command == TS_QUERY_BOOTLOADER;
523 char testOutputBuffer[64];
529 tsChannel->
write((
const uint8_t*)QUOTE(SIGNATURE_HASH),
sizeof(QUOTE(SIGNATURE_HASH)));
532 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
534 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer),
" uptime=%ds ", (
int)
getTimeNowS());
535 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
537 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer), __DATE__
" %s\r\n", PROTOCOL_TEST_RESPONSE_TAG);
538 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
540 if (hasFirmwareError()) {
542 chsnprintf(testOutputBuffer,
sizeof(testOutputBuffer),
"error=%s\r\n", error);
543 tsChannel->
write((
const uint8_t*)testOutputBuffer, strlen(testOutputBuffer));
550 if (strlen(errorMessage) == 0) {
554 tsChannel->
sendResponse(
TS_CRC,
reinterpret_cast<const uint8_t*
>(errorMessage), strlen(errorMessage),
true);
567 efiPrintf(
"TS <- Query signature: %s", signature);
568 tsChannel->
sendResponse(mode, (
const uint8_t *)signature, strlen(signature) + 1);
580 }
else if (command == TS_HELLO_COMMAND || command == TS_QUERY_COMMAND) {
582 efiPrintf(
"Got naked Query command");
585 }
else if (command == TS_TEST_COMMAND || command ==
'T') {
588 }
else if (command == TS_COMMAND_F) {
598 tsChannel->
write((
const uint8_t *)TS_PROTOCOL, strlen(TS_PROTOCOL));
613 chThdSleepMilliseconds(10);
620 size_t received = tsChannel->
readTimeout(&firstByte, 1, TS_COMMUNICATION_TIMEOUT);
622 logMsg(
"received %d\r\n", received);
627#if EFI_BLUETOOTH_SETUP
644 received = tsChannel->
readTimeout(&secondByte, 1, TS_COMMUNICATION_TIMEOUT_SHORT);
651 uint16_t incomingPacketSize = firstByte << 8 | secondByte;
652 size_t expectedSize = incomingPacketSize + TS_PACKET_TAIL_SIZE;
654 if ((incomingPacketSize == 0) || (expectedSize >
sizeof(tsChannel->
scratchBuffer))) {
656 efiPrintf(
"process_ts: channel=%s invalid size: %d", tsChannel->
name, incomingPacketSize);
659 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE,
"invalid size");
672 if (received != expectedSize) {
674 efiPrintf(
"Got only %d bytes while expecting %d for command 0x%02x", received,
675 expectedSize, command);
685 efiPrintf(
"unexpected command %x", command);
686 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"unknown");
700 received = tsChannel->
readTimeout((uint8_t*)(tsChannel->
scratchBuffer) + 1, expectedSize - 1, TS_COMMUNICATION_TIMEOUT);
701 if (received != expectedSize - 1) {
708 logMsg(
"command %c\r\n", command);
711 uint32_t expectedCrc = *(uint32_t*) (tsChannel->
scratchBuffer + incomingPacketSize);
715 uint32_t actualCrc = crc32(tsChannel->
scratchBuffer, incomingPacketSize);
716 if (actualCrc != expectedCrc) {
719 efiPrintf(
"TunerStudio: command %c actual CRC %x/expected %x", tsChannel->
scratchBuffer[0],
720 (
unsigned int)actualCrc, (
unsigned int)expectedCrc);
722 sendErrorCode(tsChannel, TS_RESPONSE_CRC_FAILURE,
"crc_issue");
734 efiPrintf(
"got unexpected TunerStudio command %x:%c", command, command);
768#if EFI_PROD_CODE || EFI_SIMULATOR
775 char versionBuffer[32];
776 chsnprintf(versionBuffer,
sizeof(versionBuffer),
"%s v%d@%u", FRONTEND_TITLE_BAR_NAME,
getRusEfiVersion(), SIGNATURE_HASH);
777 tsChannel->
sendResponse(
TS_CRC, (
const uint8_t *) versionBuffer, strlen(versionBuffer) + 1);
789 logMsg(
"get test sending [%d]\r\n", outputSize);
792 tsChannel->
writeCrcPacket(TS_RESPONSE_OK,
reinterpret_cast<const uint8_t*
>(output), outputSize,
true);
794 logMsg(
"sent [%d]\r\n", outputSize);
800 data[incomingPacketSize] = 0;
803 logMsg(
"execute [%s]\r\n", trimmed);
813 char command = data[0];
816 const uint16_t* data16 =
reinterpret_cast<uint16_t*
>(data);
825 if (incomingPacketSize >= 3) {
829 if (incomingPacketSize >= 5) {
835 case TS_OUTPUT_COMMAND:
836 if (incomingPacketSize == 1) {
838 count = TS_TOTAL_OUTPUT_SIZE;
842 case TS_OUTPUT_ALL_COMMAND:
844 count = TS_TOTAL_OUTPUT_SIZE;
848 case TS_GET_SCATTERED_GET_COMMAND:
852 criticalError(
"Slow/wireless mode not supported");
855 case TS_HELLO_COMMAND:
859 case TS_GET_FIRMWARE_VERSION:
870 case TS_CHUNK_WRITE_COMMAND:
877 case TS_CRC_CHECK_COMMAND:
884 case TS_BURN_COMMAND:
889 case TS_READ_COMMAND:
896 case TS_TEST_COMMAND:
901 case TS_GET_CONFIG_ERROR:
905 case TS_SIMULATE_CAN:
906 void handleWrapCan(
TsChannelBase* tsChannel,
char *data,
int incomingPacketSize);
907 handleWrapCan(tsChannel, data, incomingPacketSize - 1);
910 case TS_IO_TEST_COMMAND:
911#if EFI_SIMULATOR || EFI_PROD_CODE
925 case TS_SET_LOGGER_SWITCH:
927 case TS_COMPOSITE_ENABLE:
930 case TS_COMPOSITE_DISABLE:
933 case TS_COMPOSITE_READ:
943 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
948 case TS_TRIGGER_SCOPE_ENABLE:
951 case TS_TRIGGER_SCOPE_DISABLE:
954 case TS_TRIGGER_SCOPE_READ:
962 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
975 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
987 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
993 case TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY:
994 sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE, DO_NOT_LOG);
998 case TS_PERF_TRACE_BEGIN:
1002 case TS_PERF_TRACE_GET_BUFFER:
1010 case TS_PERF_TRACE_BEGIN:
1011 criticalError(
"TS_PERF_TRACE not supported");
1013 case TS_PERF_TRACE_GET_BUFFER:
1014 criticalError(
"TS_PERF_TRACE_GET_BUFFER not supported");
1017 case TS_QUERY_BOOTLOADER: {
1018 uint8_t bldata = TS_QUERY_BOOTLOADER_NONE;
1020 bldata = TS_QUERY_BOOTLOADER_OPENBLT;
1027 sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND,
"unknown_command");
1028static char tsErrorBuff[80];
1029 chsnprintf(tsErrorBuff,
sizeof(tsErrorBuff),
"ERROR: ignoring unexpected command %d [%c]", command, command);
1046 static_assert(
sizeof(
persistent_config_s) == TOTAL_CONFIG_SIZE,
"TS datapage size mismatch");
1058#if EFI_BLUETOOTH_SETUP
1063 addConsoleActionSSS(
"bluetooth_hc05", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1066 addConsoleActionSSS(
"bluetooth_hc06", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1069 addConsoleActionSSS(
"bluetooth_bk", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1072 addConsoleActionSSS(
"bluetooth_jdy", [](
const char *baudRate,
const char *name,
const char *pinCode) {
1075 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< setup_custom_board_overrides_type > board_override)
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)
static uint8_t getUserEnteredTuningDetector()
static bool isTuningDetectorUndefined()
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
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()