2022-07-15 11:10:15 -07:00
|
|
|
#include "tunerstudio_impl.h"
|
|
|
|
#include "tunerstudio.h"
|
|
|
|
#include "tunerstudio_io.h"
|
2023-01-11 00:29:22 -08:00
|
|
|
#include "byteswap.h"
|
2022-07-15 11:10:15 -07:00
|
|
|
|
|
|
|
/* configuration */
|
|
|
|
#include "port.h"
|
|
|
|
|
2023-01-11 00:29:22 -08:00
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
#include <rusefi/crc.h>
|
2022-07-18 15:26:00 -07:00
|
|
|
#include <rusefi/fragments.h>
|
|
|
|
|
2022-07-15 11:10:15 -07:00
|
|
|
void sendErrorCode(TsChannelBase *tsChannel, uint8_t code);
|
2023-01-11 00:29:22 -08:00
|
|
|
void sendOkResponse(TsChannelBase *tsChannel, ts_response_format_e mode);
|
2022-07-15 11:10:15 -07:00
|
|
|
|
2022-07-18 15:26:00 -07:00
|
|
|
FragmentList getFragments();
|
|
|
|
|
2022-07-15 11:10:15 -07:00
|
|
|
/**
|
|
|
|
* @brief 'Output' command sends out a snapshot of current values
|
|
|
|
* Gauges refresh
|
|
|
|
*/
|
|
|
|
void TunerStudio::cmdOutputChannels(TsChannelBase* tsChannel, uint16_t offset, uint16_t count) {
|
2022-07-18 12:31:09 -07:00
|
|
|
// TODO: check against total framents size
|
|
|
|
// if (offset + count > TS_TOTAL_OUTPUT_SIZE) {
|
|
|
|
// sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
|
|
|
// return;
|
|
|
|
// }
|
2022-07-15 11:10:15 -07:00
|
|
|
|
|
|
|
tsChannel->assertPacketSize(count, false);
|
|
|
|
// this method is invoked too often to print any debug information
|
|
|
|
uint8_t * scratchBuffer = (uint8_t *)tsChannel->scratchBuffer;
|
|
|
|
/**
|
|
|
|
* collect data from all models
|
|
|
|
*/
|
2022-07-18 12:31:09 -07:00
|
|
|
copyRange(scratchBuffer + 3, getFragments(), offset, count);
|
2022-07-15 11:10:15 -07:00
|
|
|
|
|
|
|
tsChannel->crcAndWriteBuffer(TS_RESPONSE_OK, count);
|
|
|
|
}
|
2023-01-11 00:29:22 -08:00
|
|
|
|
|
|
|
// Validate whether the specified offset and count would cause an overrun in the tune.
|
|
|
|
// Returns true if offset and count are in valid range
|
|
|
|
bool TunerStudio::validateScatterOffsetCount(size_t offset, size_t count) {
|
|
|
|
if (offset + count > sizeof(highSpeedOffsets))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TunerStudio::handleScatteredReadCommand(TsChannelBase* tsChannel) {
|
|
|
|
#ifdef HIGH_SPEED_OPTIMIZED
|
|
|
|
uint8_t *buffer = (uint8_t *)tsChannel->scratchBuffer;
|
|
|
|
tsChannel->writeHeader(TS_RESPONSE_OK, highSpeedTotalSize);
|
|
|
|
for (size_t i = 0; i < highSpeedChunks; i++) {
|
|
|
|
chDbgAssert(NULL != highSpeedPtrs[i], "NULL pointer in scatter list");
|
|
|
|
// copy to temp buffer to avoid changes before transmission, couse it can affect CRC
|
|
|
|
memcpy(buffer, highSpeedPtrs[i], highSpeedSizes[i]);
|
|
|
|
tsChannel->writeBody(buffer, highSpeedSizes[i]);
|
|
|
|
}
|
|
|
|
tsChannel->writeTail();
|
|
|
|
#else
|
|
|
|
size_t count = 0;
|
|
|
|
uint8_t *buffer = (uint8_t *)tsChannel->scratchBuffer + 3; /* reserve 3 bytes for header */
|
|
|
|
|
|
|
|
for (size_t i = 0; i < HIGH_SPEED_COUNT; i++) {
|
|
|
|
int packed = highSpeedOffsets[i];
|
|
|
|
int type = packed >> 13;
|
|
|
|
|
|
|
|
if (type == 0)
|
|
|
|
continue;
|
|
|
|
int size = 1 << (type - 1);
|
|
|
|
|
|
|
|
int offset = packed & 0x1FFF;
|
|
|
|
// write each data point and CRC incrementally
|
|
|
|
copyRange(buffer + count, getFragments(), offset, size);
|
|
|
|
count += size;
|
|
|
|
}
|
|
|
|
tsChannel->crcAndWriteBuffer(TS_RESPONSE_OK, count);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void TunerStudio::handleScatterListWriteCommand(TsChannelBase* tsChannel, uint16_t offset, uint16_t count, void *content)
|
|
|
|
{
|
|
|
|
uint8_t * addr = (uint8_t *)highSpeedOffsets + offset;
|
|
|
|
memcpy(addr, content, count);
|
|
|
|
|
|
|
|
#ifdef HIGH_SPEED_OPTIMIZED
|
|
|
|
highSpeedChunks = 0;
|
|
|
|
highSpeedTotalSize = 0;
|
|
|
|
/* translate to CPU pointers */
|
|
|
|
for (int i = 0; i < HIGH_SPEED_COUNT; i++) {
|
|
|
|
int packed = highSpeedOffsets[i];
|
|
|
|
int type = packed >> 13;
|
|
|
|
|
|
|
|
if (type == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int size = 1 << (type - 1);
|
|
|
|
int offset = packed & 0x1FFF;
|
|
|
|
highSpeedTotalSize += size;
|
|
|
|
|
|
|
|
uint8_t *ptr;
|
|
|
|
|
|
|
|
do {
|
|
|
|
size_t availSize = getRangePtr(&ptr, getFragments(), offset, size);
|
|
|
|
|
|
|
|
/* note: no need to check ptr for NULL */
|
|
|
|
if ((highSpeedChunks == 0) || /* first chunk */
|
|
|
|
((highSpeedChunks > 0) &&
|
|
|
|
(highSpeedPtrs[highSpeedChunks - 1] + highSpeedSizes[highSpeedChunks - 1] != ptr))) /* or not contiguous chunks */ {
|
|
|
|
highSpeedPtrs[highSpeedChunks] = ptr;
|
|
|
|
highSpeedSizes[highSpeedChunks] = size;
|
|
|
|
highSpeedChunks++;
|
|
|
|
} else {
|
|
|
|
/* unite */
|
|
|
|
highSpeedSizes[highSpeedChunks - 1] += size;
|
|
|
|
}
|
|
|
|
size -= availSize;
|
|
|
|
offset += availSize;
|
|
|
|
} while (size);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sendOkResponse(tsChannel, TS_CRC);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TunerStudio::handleScatterListReadCommand(TsChannelBase* tsChannel, uint16_t offset, uint16_t count)
|
|
|
|
{
|
|
|
|
if (!validateScatterOffsetCount(offset, count)) {
|
|
|
|
tunerStudioError(tsChannel, "ERROR: out of range");
|
|
|
|
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t * addr = (uint8_t *)highSpeedOffsets + offset;
|
|
|
|
tsChannel->sendResponse(TS_CRC, addr, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TunerStudio::handleScatterListCrc32Check(TsChannelBase *tsChannel, uint16_t offset, uint16_t count)
|
|
|
|
{
|
|
|
|
// Ensure we are reading from in bounds
|
|
|
|
if (!validateScatterOffsetCount(offset, count)) {
|
|
|
|
tunerStudioError(tsChannel, "ERROR: out of range");
|
|
|
|
sendErrorCode(tsChannel, TS_RESPONSE_OUT_OF_RANGE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t* start = (uint8_t *)highSpeedOffsets + offset;
|
|
|
|
|
|
|
|
uint32_t crc = SWAP_UINT32(crc32(start, count));
|
|
|
|
tsChannel->sendResponse(TS_CRC, (const uint8_t *) &crc, 4);
|
|
|
|
}
|