From f657fc6293c4e8da94d80521b4c318898e6d3fe1 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Tue, 10 Oct 2023 15:49:36 +1100 Subject: [PATCH] Add option on secondary serial to use previous generic data list --- reference/speeduino.ini | 8 +- speeduino/comms_legacy.cpp | 12 +-- speeduino/comms_legacy.h | 1 + speeduino/comms_secondary.cpp | 8 +- speeduino/comms_secondary.h | 9 ++- speeduino/globals.h | 4 +- speeduino/logger.cpp | 140 ++++++++++++++++++++++++++++++++++ speeduino/logger.h | 1 + 8 files changed, 165 insertions(+), 18 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 965a73ac..20f64ae1 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -824,7 +824,7 @@ page = 9 enable_secondarySerial = bits, U08, 0, [0:0], "Disable", "Enable" intcan_available = bits, U08, 0, [1:1], "Disable", "Enable" enable_intcan = bits, U08, 0, [2:2], "Disable", "Enable" - secondarySerialProtocol = bits, U08, 0, [3:5], "Generic". "CAN", "msDroid", "Real Dash", "INVALID", "INVALID", "INVALID", "INVALID" + secondarySerialProtocol = bits, U08, 0, [3:6], "Generic (Fixed List)". "Generic (ini File)". "CAN", "msDroid", "Real Dash", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" caninput_sel0a = bits, U08, 1, [0:1], "Off", "INVALID", "Analog_local", "Digital_local" caninput_sel0b = bits, U08, 1, [2:3], "Off", "External Source", "Analog_local", "Digital_local" @@ -5398,11 +5398,11 @@ cmdVSSratio6 = "E\x99\x06" CLIdleDelta = { CLIdleTarget - rpm } syncStatus = { halfSync + (sync << 1) } #if mcu_teensy - CANisAvailable = { ( (enable_secondarySerial && (secondarySerialProtocol == 1)) || (enable_intcan)) } + CANisAvailable = { ( (enable_secondarySerial && (secondarySerialProtocol == 2)) || (enable_intcan)) } #elif mcu_stm32 - CANisAvailable = { ( (enable_secondarySerial && (secondarySerialProtocol == 1)) || (enable_intcan)) } + CANisAvailable = { ( (enable_secondarySerial && (secondarySerialProtocol == 2)) || (enable_intcan)) } #else - CANisAvailable = { (enable_secondarySerial && (secondarySerialProtocol == 1)) } + CANisAvailable = { (enable_secondarySerial && (secondarySerialProtocol == 2)) } #endif ;------------------------------------------------------------------------------- diff --git a/speeduino/comms_legacy.cpp b/speeduino/comms_legacy.cpp index 735fe2fc..82ffa430 100644 --- a/speeduino/comms_legacy.cpp +++ b/speeduino/comms_legacy.cpp @@ -36,7 +36,6 @@ byte inProgressLength; SerialStatus serialStatusFlag; SerialStatus serialSecondaryStatusFlag; - static bool isMap(void) { // Detecting if the current page is a table/map return (currentPage == veMapPage) || (currentPage == ignMapPage) || (currentPage == afrMapPage) || (currentPage == fuelMap2Page) || (currentPage == ignMap2Page); @@ -665,16 +664,18 @@ void legacySerialHandler(byte cmd, Stream &targetPort, SerialStatus &targetStatu * @param cmd - ??? - Will be used as some kind of ack on secondarySerial * @param targetPort - The HardwareSerial device that will be transmitted to * @param targetStatusFlag - The status flag that will be set to indicate the status of the transmission + * @param logFunction - The function that should be called to retrieve the log value * E.g. tuning sw command 'A' (Send all values) will send data from field number 0, LOG_ENTRY_SIZE fields. * @return the current values of a fixed group of variables */ -void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag) +void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag) { sendValues(offset, packetLength, cmd, targetPort, targetStatusFlag, &getTSLogEntry); } //Defaults to using the standard TS log function +void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag, uint8_t (*logFunction)(uint16_t)) { #if defined(secondarySerial_AVAILABLE) if (&targetPort == &secondarySerial) { //CAN serial - if( (configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC) || (configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_REALDASH)) + if( (configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC_FIXED) || (configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC_INI) || (configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_REALDASH)) { if (cmd == 0x30) { @@ -711,9 +712,10 @@ void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &target { bool bufferFull = false; - targetPort.write(getTSLogEntry(offset+x)); + //targetPort.write(getTSLogEntry(offset+x)); + targetPort.write(logFunction(offset+x)); - if( (&targetPort == &Serial) || (configPage9.secondarySerialProtocol != SECONDARY_SERIAL_PROTO_REALDASH) ) + if( (&targetPort == &Serial) ) { //If the transmit buffer is full, wait for it to clear. This cannot be used with Read Dash as it will cause a timeout if(targetPort.availableForWrite() < 1) { bufferFull = true; } diff --git a/speeduino/comms_legacy.h b/speeduino/comms_legacy.h index b5510480..f54fccf0 100644 --- a/speeduino/comms_legacy.h +++ b/speeduino/comms_legacy.h @@ -76,6 +76,7 @@ extern byte inProgressLength; void legacySerialCommand(void);//This is the heart of the Command Line Interpreter. All that needed to be done was to make it human readable. void legacySerialHandler(byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag); void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag); +void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag, uint8_t (*logFunction)(uint16_t)); void sendValuesLegacy(void); void sendPage(void); void sendPageASCII(void); diff --git a/speeduino/comms_secondary.cpp b/speeduino/comms_secondary.cpp index 52ae9b95..8604fa6a 100644 --- a/speeduino/comms_secondary.cpp +++ b/speeduino/comms_secondary.cpp @@ -50,8 +50,8 @@ void secondserial_Command(void) { case 'A': // sends a fixed 75 bytes of data. Used by Real Dash (Among others) - //sendcanValues(0, CAN_PACKET_SIZE, 0x31, 1); //send values to serial3 - sendValues(0, CAN_PACKET_SIZE, 0x31, secondarySerial, serialSecondaryStatusFlag); //send values to serial3 + if(configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC_FIXED) { sendValues(0, CAN_PACKET_SIZE, 0x31, secondarySerial, serialSecondaryStatusFlag, &getLegacySecondarySerialLogEntry); } // Send values using the legacy fixed byte order + else { sendValues(0, CAN_PACKET_SIZE, 0x31, secondarySerial, serialSecondaryStatusFlag); } //send values to serial3 using the order in the ini file break; case 'b': // New EEPROM burn command to only burn a single page at a time @@ -139,7 +139,9 @@ void secondserial_Command(void) } case 'n': // sends the bytes of realtime values from the NEW CAN list - sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, secondarySerial, serialSecondaryStatusFlag); //send values to serial3 + //sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, secondarySerial, serialSecondaryStatusFlag); //send values to serial3 + if(configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC_FIXED) { sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, secondarySerial, serialSecondaryStatusFlag, &getLegacySecondarySerialLogEntry); } // Send values using the legacy fixed byte order + else { sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, secondarySerial, serialSecondaryStatusFlag); } //send values to serial3 using the order in the ini file break; case 'p': diff --git a/speeduino/comms_secondary.h b/speeduino/comms_secondary.h index bd7741de..e52759d7 100644 --- a/speeduino/comms_secondary.h +++ b/speeduino/comms_secondary.h @@ -4,10 +4,11 @@ #define NEW_CAN_PACKET_SIZE 123 #define CAN_PACKET_SIZE 75 -#define SECONDARY_SERIAL_PROTO_GENERIC 0 -#define SECONDARY_SERIAL_PROTO_CAN 1 -#define SECONDARY_SERIAL_PROTO_MSDROID 2 -#define SECONDARY_SERIAL_PROTO_REALDASH 3 +#define SECONDARY_SERIAL_PROTO_GENERIC_FIXED 0 +#define SECONDARY_SERIAL_PROTO_GENERIC_INI 1 +#define SECONDARY_SERIAL_PROTO_CAN 2 +#define SECONDARY_SERIAL_PROTO_MSDROID 3 +#define SECONDARY_SERIAL_PROTO_REALDASH 4 #if ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ) #define secondarySerial_AVAILABLE diff --git a/speeduino/globals.h b/speeduino/globals.h index 5990d483..a97647d6 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -1118,8 +1118,8 @@ struct config9 { byte enable_secondarySerial:1; //enable secondary serial byte intcan_available:1; //enable internal can module byte enable_intcan:1; - byte secondarySerialProtocol:3; //protocol for secondary serial. 0=Generic, 1=CAN, 2=msDroid, 3=Real Dash - byte unused9_0:2; + byte secondarySerialProtocol:4; //protocol for secondary serial. 0=Generic (Fixed list), 1=Generic (ini based list), 2=CAN, 3=msDroid, 4=Real Dash + byte unused9_0:1; byte caninput_sel[16]; //bit status on/Can/analog_local/digtal_local if input is enabled uint16_t caninput_source_can_address[16]; //u16 [15] array holding can address of input diff --git a/speeduino/logger.cpp b/speeduino/logger.cpp index 19d9e804..1438828e 100644 --- a/speeduino/logger.cpp +++ b/speeduino/logger.cpp @@ -335,6 +335,146 @@ float getReadableFloatLogEntry(uint16_t logIndex) } #endif +uint8_t getLegacySecondarySerialLogEntry(uint16_t byteNum) +{ + uint8_t statusValue = 0; + currentStatus.spark ^= (-currentStatus.hasSync ^ currentStatus.spark) & (1U << BIT_SPARK_SYNC); //Set the sync bit of the Spark variable to match the hasSync variable + + switch(byteNum) + { + case 0: statusValue = currentStatus.secl; break; //secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0) + case 1: statusValue = currentStatus.status1; break; //status1 Bitfield, inj1Status(0), inj2Status(1), inj3Status(2), inj4Status(3), DFCOOn(4), boostCutFuel(5), toothLog1Ready(6), toothLog2Ready(7) + case 2: statusValue = currentStatus.engine; break; //Engine Status Bitfield, running(0), crank(1), ase(2), warmup(3), tpsaccaen(4), tpsacden(5), mapaccaen(6), mapaccden(7) + case 3: statusValue = (byte)div100(currentStatus.dwell); break; //Dwell in ms * 10 + case 4: statusValue = lowByte(currentStatus.MAP); break; //2 bytes for MAP + case 5: statusValue = highByte(currentStatus.MAP); break; + case 6: statusValue = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); break; //mat + case 7: statusValue = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); break; //Coolant ADC + case 8: statusValue = currentStatus.batCorrection; break; //Battery voltage correction (%) + case 9: statusValue = currentStatus.battery10; break; //battery voltage + case 10: statusValue = currentStatus.O2; break; //O2 + case 11: statusValue = currentStatus.egoCorrection; break; //Exhaust gas correction (%) + case 12: statusValue = currentStatus.iatCorrection; break; //Air temperature Correction (%) + case 13: statusValue = currentStatus.wueCorrection; break; //Warmup enrichment (%) + case 14: statusValue = lowByte(currentStatus.RPM); break; //rpm HB + case 15: statusValue = highByte(currentStatus.RPM); break; //rpm LB + case 16: statusValue = currentStatus.AEamount; break; //acceleration enrichment (%) + case 17: statusValue = currentStatus.corrections; break; //Total GammaE (%) + case 18: statusValue = currentStatus.VE; break; //Current VE 1 (%) + case 19: statusValue = currentStatus.afrTarget; break; + case 20: statusValue = lowByte(currentStatus.PW1); break; //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS. + case 21: statusValue = highByte(currentStatus.PW1); break; //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS. + case 22: statusValue = (uint8_t)(currentStatus.tpsDOT / 10); break; //TPS DOT + case 23: statusValue = currentStatus.advance; break; + case 24: statusValue = currentStatus.TPS; break; // TPS (0% to 100%) + case 25: statusValue = lowByte(currentStatus.loopsPerSecond); break; + case 26: statusValue = highByte(currentStatus.loopsPerSecond); break; + + case 27: currentStatus.freeRAM = freeRam(); statusValue = lowByte(currentStatus.freeRAM); break; //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF); break; + case 28: currentStatus.freeRAM = freeRam(); statusValue = highByte(currentStatus.freeRAM); break; + + case 29: statusValue = (byte)(currentStatus.boostTarget >> 1); break; //Divide boost target by 2 to fit in a byte + case 30: statusValue = (byte)(currentStatus.boostDuty / 100); break; + case 31: statusValue = currentStatus.spark; break; //Spark related bitfield, launchHard(0), launchSoft(1), hardLimitOn(2), softLimitOn(3), boostCutSpark(4), error(5), idleControlOn(6), sync(7) + case 32: statusValue = lowByte(currentStatus.rpmDOT); break; + case 33: statusValue = highByte(currentStatus.rpmDOT); break; + case 34: statusValue = currentStatus.ethanolPct; break; //Flex sensor value (or 0 if not used) + case 35: statusValue = currentStatus.flexCorrection; break; //Flex fuel correction (% above or below 100) + case 36: statusValue = currentStatus.flexIgnCorrection; break; //Ignition correction (Increased degrees of advance) for flex fuel + case 37: statusValue = currentStatus.idleLoad; break; + case 38: statusValue = currentStatus.testOutputs; break; // testEnabled(0), testActive(1) + case 39: statusValue = currentStatus.O2_2; break; //O2 + case 40: statusValue = currentStatus.baro; break; //Barometer value + case 41: statusValue = lowByte(currentStatus.canin[0]); break; + case 42: statusValue = highByte(currentStatus.canin[0]); break; + case 43: statusValue = lowByte(currentStatus.canin[1]); break; + case 44: statusValue = highByte(currentStatus.canin[1]); break; + case 45: statusValue = lowByte(currentStatus.canin[2]); break; + case 46: statusValue = highByte(currentStatus.canin[2]); break; + case 47: statusValue = lowByte(currentStatus.canin[3]); break; + case 48: statusValue = highByte(currentStatus.canin[3]); break; + case 49: statusValue = lowByte(currentStatus.canin[4]); break; + case 50: statusValue = highByte(currentStatus.canin[4]); break; + case 51: statusValue = lowByte(currentStatus.canin[5]); break; + case 52: statusValue = highByte(currentStatus.canin[5]); break; + case 53: statusValue = lowByte(currentStatus.canin[6]); break; + case 54: statusValue = highByte(currentStatus.canin[6]); break; + case 55: statusValue = lowByte(currentStatus.canin[7]); break; + case 56: statusValue = highByte(currentStatus.canin[7]); break; + case 57: statusValue = lowByte(currentStatus.canin[8]); break; + case 58: statusValue = highByte(currentStatus.canin[8]); break; + case 59: statusValue = lowByte(currentStatus.canin[9]); break; + case 60: statusValue = highByte(currentStatus.canin[9]); break; + case 61: statusValue = lowByte(currentStatus.canin[10]); break; + case 62: statusValue = highByte(currentStatus.canin[10]); break; + case 63: statusValue = lowByte(currentStatus.canin[11]); break; + case 64: statusValue = highByte(currentStatus.canin[11]); break; + case 65: statusValue = lowByte(currentStatus.canin[12]); break; + case 66: statusValue = highByte(currentStatus.canin[12]); break; + case 67: statusValue = lowByte(currentStatus.canin[13]); break; + case 68: statusValue = highByte(currentStatus.canin[13]); break; + case 69: statusValue = lowByte(currentStatus.canin[14]); break; + case 70: statusValue = highByte(currentStatus.canin[14]); break; + case 71: statusValue = lowByte(currentStatus.canin[15]); break; + case 72: statusValue = highByte(currentStatus.canin[15]); break; + + case 73: statusValue = currentStatus.tpsADC; break; + case 74: statusValue = getNextError(); break; // errorNum (0:1), currentError(2:7) + + case 75: statusValue = currentStatus.launchCorrection; break; + case 76: statusValue = lowByte(currentStatus.PW2); break; //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS. + case 77: statusValue = highByte(currentStatus.PW2); break; //Pulsewidth 2 multiplied by 10 in ms. Have to convert from uS to mS. + case 78: statusValue = lowByte(currentStatus.PW3); break; //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS. + case 79: statusValue = highByte(currentStatus.PW3); break; //Pulsewidth 3 multiplied by 10 in ms. Have to convert from uS to mS. + case 80: statusValue = lowByte(currentStatus.PW4); break; //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS. + case 81: statusValue = highByte(currentStatus.PW4); break; //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS. + + case 82: statusValue = currentStatus.status3; break; // resentLockOn(0), nitrousOn(1), fuel2Active(2), vssRefresh(3), halfSync(4), nSquirts(6:7) + case 83: statusValue = currentStatus.engineProtectStatus; break; //RPM(0), MAP(1), OIL(2), AFR(3), Unused(4:7) + case 84: statusValue = lowByte(currentStatus.fuelLoad); break; + case 85: statusValue = highByte(currentStatus.fuelLoad); break; + case 86: statusValue = lowByte(currentStatus.ignLoad); break; + case 87: statusValue = highByte(currentStatus.ignLoad); break; + case 88: statusValue = lowByte(currentStatus.injAngle); break; + case 89: statusValue = highByte(currentStatus.injAngle); break; + case 90: statusValue = currentStatus.idleLoad; break; + case 91: statusValue = currentStatus.CLIdleTarget; break; //closed loop idle target + case 92: statusValue = (uint8_t)(currentStatus.mapDOT / 10); break; //rate of change of the map + case 93: statusValue = (int8_t)currentStatus.vvt1Angle; break; + case 94: statusValue = currentStatus.vvt1TargetAngle; break; + case 95: statusValue = currentStatus.vvt1Duty; break; + case 96: statusValue = lowByte(currentStatus.flexBoostCorrection); break; + case 97: statusValue = highByte(currentStatus.flexBoostCorrection); break; + case 98: statusValue = currentStatus.baroCorrection; break; + case 99: statusValue = currentStatus.ASEValue; break; //Current ASE (%) + case 100: statusValue = lowByte(currentStatus.vss); break; //speed reading from the speed sensor + case 101: statusValue = highByte(currentStatus.vss); break; + case 102: statusValue = currentStatus.gear; break; + case 103: statusValue = currentStatus.fuelPressure; break; + case 104: statusValue = currentStatus.oilPressure; break; + case 105: statusValue = currentStatus.wmiPW; break; + case 106: statusValue = currentStatus.status4; break; // wmiEmptyBit(0), vvt1Error(1), vvt2Error(2), fanStatus(3), UnusedBits(4:7) + case 107: statusValue = (int8_t)currentStatus.vvt2Angle; break; + case 108: statusValue = currentStatus.vvt2TargetAngle; break; + case 109: statusValue = currentStatus.vvt2Duty; break; + case 110: statusValue = currentStatus.outputsStatus; break; + case 111: statusValue = (byte)(currentStatus.fuelTemp + CALIBRATION_TEMPERATURE_OFFSET); break; //Fuel temperature from flex sensor + case 112: statusValue = currentStatus.fuelTempCorrection; break; //Fuel temperature Correction (%) + case 113: statusValue = currentStatus.VE1; break; //VE 1 (%) + case 114: statusValue = currentStatus.VE2; break; //VE 2 (%) + case 115: statusValue = currentStatus.advance1; break; //advance 1 + case 116: statusValue = currentStatus.advance2; break; //advance 2 + case 117: statusValue = currentStatus.nitrous_status; break; + case 118: statusValue = currentStatus.TS_SD_Status; break; //SD card status + case 119: statusValue = lowByte(currentStatus.EMAP); break; //2 bytes for EMAP + case 120: statusValue = highByte(currentStatus.EMAP); break; + case 121: statusValue = currentStatus.fanDuty; break; + case 122: statusValue = currentStatus.airConStatus; break; + } + + return statusValue; +} + /** * Searches the log 2 byte array to determine whether a given index is a regular single byte or a 2 byte field * Uses a boundless binary search for improved performance, but requires the fsIntIndex to remain in order diff --git a/speeduino/logger.h b/speeduino/logger.h index 62dc123c..22930bb8 100644 --- a/speeduino/logger.h +++ b/speeduino/logger.h @@ -22,6 +22,7 @@ int16_t getReadableLogEntry(uint16_t logIndex); #if defined(FPU_MAX_SIZE) && FPU_MAX_SIZE >= 32 //cppcheck-suppress misra-c2012-20.9 float getReadableFloatLogEntry(uint16_t logIndex); #endif +uint8_t getLegacySecondarySerialLogEntry(uint16_t byteNum); bool is2ByteEntry(uint8_t key); void startToothLogger(void);