From 5140b3182993bb2e750d169812014ad9e11bb29c Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Thu, 5 Oct 2023 22:24:13 +1100 Subject: [PATCH] Initial work cleaning up Secondary Serial incl msDroid compat option Fixes #1106 --- reference/speeduino.ini | 67 ++++++------ speeduino/cancomms.h | 5 + speeduino/cancomms.ino | 94 +++++++---------- speeduino/comms.cpp | 2 +- speeduino/comms_legacy.cpp | 203 +++++++++++++++++++++++++++---------- speeduino/comms_legacy.h | 3 +- speeduino/globals.h | 3 + 7 files changed, 236 insertions(+), 141 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index da0b91f4..72186c38 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -1,5 +1,4 @@ ;------------------------------------------------------------------------------- -#unset CAN_COMMANDS #unset enablehardware_test [MegaTune] @@ -45,6 +44,10 @@ settingOption = COMMS_COMPAT, "Compatibility Mode" settingOption = DEFAULT, "Normal" + settingGroup = COMMS_MSDROID_COMPAT, "msDroid Compatibility-ONLY enable on Android" + settingOption = MSDROID_COMPAT, "Enable" + settingOption = DEFAULT, "Disable" + [PcVariables] ; valid types: boolean, double, int, list ; @@ -263,8 +266,12 @@ interWriteDelay = 10 ;Ignored when tsWriteBlocks is on pageActivationDelay = 10 restrictSquirtRelationship = false ;This requires TS 3.1 or above + #if MSDROID_COMPAT + ;Do nothing + #else messageEnvelopeFormat = msEnvelope_1.0 ;New and testing only tableCrcCommand = "k\$tsCanId%2i%2o%2c" ;TS can only use this command in new mode + #endif readSdCompressed = false ;New for TS 3.0.08ish upwards, define lists of standard I/O options @@ -817,6 +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" 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" @@ -1938,6 +1946,7 @@ menuDialog = main subMenu = NitrousControl, "Nitrous" subMenu = vssSettings, "VSS and Gear detection" subMenu = airCon, "Air Conditioning Control" + subMenu = pressureSensors, "Fuel/Oil pressure" subMenu = std_separator subMenu = boostSettings, "Boost Control" subMenu = boostLoad, "Boost Targets/Duty", 8, { boostEnabled } @@ -1953,22 +1962,14 @@ menuDialog = main subMenu = std_separator - #if CAN_COMMANDS subMenu = can_serial3IO, "Canbus/Secondary Serial IO Interface" - subMenu = CanBcast, "CAN Broadcasting menu", { enable_intcan && intcan_available } + subMenu = CanBcast, "CAN Broadcasting menu", { CANisAvailable } subMenu = std_separator - subMenu = Canin_config, "External Auxillary Input Channel Configuration", {enable_secondarySerial || (enable_intcan && intcan_available)} + subMenu = Canin_config, "External Auxillary Input Channel Configuration", {enable_secondarySerial || CANisAvailable } subMenu = Auxin_config, "Local Auxillary Input Channel Configuration" ;subMenu = std_separator ;subMenu = Canout_config, "Canbus Output Configuration" - #else - subMenu = serial3IO, "Canbus/Secondary Serial IO Interface" - subMenu = CanBcast, "CAN Broadcasting menu", { enable_intcan && intcan_available } - subMenu = std_separator - subMenu = Canin_config, "External Auxiliary Input Channel Configuration", {enable_secondarySerial || (enable_intcan && intcan_available)} - subMenu = Auxin_config, "Local Auxiliary Input Channel Configuration" - #endif - subMenu = pressureSensors, "Fuel/Oil pressure" + menuDialog = main menu = "Tools" @@ -2065,13 +2066,13 @@ menuDialog = main fanSP = "The trigger temperature for the fan. Fan will be enabled above this temp" airConEnable = "Whether we are doing A/C control" - airConCompPol = "Normal should be used in most cases - where a logic HIGH output turns on the output power transistor, which is the ON state. Inverted makes logic LOW the ON state, in the rare case that turning off the transistor turns the compressor on, or you are using some sort of depletion mode FET". + airConCompPol = "Normal should be used in most cases - where a logic HIGH output turns on the output power transistor, which is the ON state. Inverted makes logic LOW the ON state, in the rare case that turning off the transistor turns the compressor on, or you are using some sort of depletion mode FET." airConReqPol = "Normal should be used in most cases - where the A/C button provides a ground when pressed. Inverted removes the internal pullup resistor, and makes +5V the ON signal instead of ground." airConTurnsFanOn = "Whether the cooling fan turns on when the A/C compressor is running." airConCompPin = "The Arduino pin that the A/C request compressor signal is output on. This is NOT necesarrily the same as the connector pin on any particlar board." airConReqPin = "The Arduino pin that the A/C request control signal is input on. This is NOT necesarrily the same as the connector pin on any particlar board." airConFanPin = "The Arduino pin that the A/C fan control signal is output on (if enabled). This is only needed if you have a stand-alone A/C fan, separate to the cooling fan (which can be enabled to come on with the A/C compressor). This is NOT necesarrily the same as the connector pin on any particlar board." - airConFanPol = "Normal should be used in most cases - where a logic HIGH output turns on the output power transistor, which is the ON state. Inverted makes logic LOW the ON state, in the rare case that turning off the transistor turns the fan on, or you are using some sort of depletion mode FET". + airConFanPol = "Normal should be used in most cases - where a logic HIGH output turns on the output power transistor, which is the ON state. Inverted makes logic LOW the ON state, in the rare case that turning off the transistor turns the fan on, or you are using some sort of depletion mode FET." airConFanEnabled = "Enable/disable stand-alone A/C fan. This would be a separate fan that only comes on when the A/C compressor is engaged, and should not be needed if the main cooling fan comes on with the A/C." airConTPSCut = "The TPS position at which the air compressor will be locked out and turn off. When TPS falls below this level (minus a 5% hysteresis), the A/C compressor will kick back in after the delay period (TPS Cut Time), provided the A/C request signal is still present." airConMinRPM = "The minimum RPM at which we will allow the A/C compressor to run (this setting is in 10 RPM steps)." @@ -2198,7 +2199,9 @@ menuDialog = main incorporateAFR = "When enabled, the AFR stoich/AFR target -ratio is incorporated directly in the pulsewidth calculation. When enabled, AFR target table affects pulsewidth even with EGO disabled. VE table must be retuned when this value is changed." useExtBaro = "By Default, Speeduino will measure barometric pressure upon startup. Optionally however, a 2nd pressure sensor can be used to perform live barometric readings whilst the system is on." - enable_secondarySerial = "This Enables the secondary serial port . Secondary serial is serial3 on mega2560 processor, and Serial2 on STM32 and Teensy processor " + enable_secondarySerial = "This Enables the secondary serial port . Secondary serial is serial3 on mega2560 processor, and Serial2 on STM32 and Teensy processor" + secondarySerialProtocol = "The protocol or application to be attached to the secondary serial port" + intcan_available = "Enables the internal CANBUS interface. This is only available on STM32 and Teensy processors" ;speeduino_tsCanId = "This is the TsCanId that the Speeduino ECU will respond to. This should match the main controller CAN ID in project properties if it is connected directly to TunerStudio, Otherwise the device ID if connected via CAN passthrough" true_address = "This is the 11bit Can address of the Speeduino ECU " @@ -3808,22 +3811,19 @@ menuDialog = main dialog = can_serial3IO, "CanBus/Secondary Serial IO interface" topicHelp = "http://wiki.speeduino.com/en/Secondary_Serial_IO_interface" field = "Enable Second Serial", enable_secondarySerial - field = "Enable Internal Canbus", enable_intcan + field = "Second Serial protocol", secondarySerialProtocol, { enable_secondarySerial } + #if mcu_teensy + field = "Enable Internal Canbus", enable_intcan + #elif mcu_stm32 + field = "Enable Internal Canbus", enable_intcan + #endif ; field = "Speeduino TsCanId", speeduino_tsCanId - field = "True Canbus Address", true_address, {enable_secondarySerial||enable_intcan} - field = "NOTE! Realtime Data Base Address MUST be at least 0x16 GREATER than the True Address as they are reserved for future expansion" - field = "Realtime Data Base Can Address", realtime_base_address, {enable_secondarySerial||enable_intcan} - field = "Speeduino OBD address", obd_address - - dialog = serial3IO, "Secondary Serial IO interface" - topicHelp = "http://wiki.speeduino.com/en/Secondary_Serial_IO_interface" - field = "Enable Second Serial", enable_secondarySerial - field = "Enable Internal Canbus", enable_intcan - ; field = "Speeduino TsCanId", speeduino_tsCanId - field = "True Canbus Address", true_address, {enable_secondarySerial||enable_intcan} - field = "NOTE! Realtime Data Base Address MUST be at least 0x16 GREATER than the True Address as they are reserved for future expansion" - field = "Realtime Data Base Can Address", realtime_base_address, {enable_secondarySerial||enable_intcan} - field = "Speeduino OBD address", obd_address + ;field = "True Canbus Address", true_address, {enable_secondarySerial||enable_intcan} + field = "True Canbus Address", true_address, { CANisAvailable } + + field = "#NOTE Realtime Data Base Address MUST be at least 0x16 GREATER than the True Address as they are reserved for future expansion" + field = "Realtime Data Base Can Address", realtime_base_address, { CANisAvailable } + field = "Speeduino OBD address", obd_address, { CANisAvailable } dialog = reset_control, "Reset Control" topicHelp = "http://wiki.speeduino.com/en/configuration/Reset_Control#settings-in-tuner-studio" @@ -5395,6 +5395,13 @@ cmdVSSratio6 = "E\x99\x06" CLIdleDelta = { CLIdleTarget - rpm } syncStatus = { halfSync + (sync << 1) } + #if mcu_teensy + CANisAvailable = { ( (enable_secondarySerial && (secondarySerialProtocol == 1)) || (enable_intcan)) } + #elif mcu_stm32 + CANisAvailable = { ( (enable_secondarySerial && (secondarySerialProtocol == 1)) || (enable_intcan)) } + #else + CANisAvailable = { (enable_secondarySerial && (secondarySerialProtocol == 1)) } + #endif ;------------------------------------------------------------------------------- [Datalog] diff --git a/speeduino/cancomms.h b/speeduino/cancomms.h index bc25dc5c..b51443fd 100644 --- a/speeduino/cancomms.h +++ b/speeduino/cancomms.h @@ -4,6 +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 + #if ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ) #define CANSerial_AVAILABLE extern HardwareSerial &CANSerial; diff --git a/speeduino/cancomms.ino b/speeduino/cancomms.ino index d08ca0d6..b74b9d70 100644 --- a/speeduino/cancomms.ino +++ b/speeduino/cancomms.ino @@ -22,8 +22,9 @@ sendcancommand is called when a command is to be sent either to serial3 #include "utilities.h" #include "comms_legacy.h" #include "logger.h" +#include "page_crc.h" -uint8_t currentsecondserialCommand; +uint8_t currentSecondaryCommand; uint8_t currentCanPage = 1;//Not the same as the speeduino config page numbers uint8_t nCanretry = 0; //no of retrys uint8_t cancmdfail = 0; //command fail yes/no @@ -31,7 +32,6 @@ uint8_t canlisten = 0; uint8_t Lbuffer[8]; //8 byte buffer to store incoming can data uint8_t Gdata[9]; uint8_t Glow, Ghigh; -bool canCmdPending = false; #if ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ) HardwareSerial &CANSerial = Serial3; @@ -51,21 +51,35 @@ bool canCmdPending = false; void secondserial_Command(void) { #if defined(CANSerial_AVAILABLE) - if (! canCmdPending) { currentsecondserialCommand = CANSerial.read(); } + if ( serialSecondaryStatusFlag == SERIAL_INACTIVE ) { currentSecondaryCommand = CANSerial.read(); } - switch (currentsecondserialCommand) + switch (currentSecondaryCommand) { 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, SERIAL_PORT_SECONDARY); //send values to serial3 - break; + // 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, CANSerial); //send values to serial3 + break; + + case 'b': // New EEPROM burn command to only burn a single page at a time + legacySerialHandler(currentSecondaryCommand, CANSerial, serialSecondaryStatusFlag); + break; + + case 'B': // AS above but for the serial compatibility mode. + BIT_SET(currentStatus.status4, BIT_STATUS4_COMMS_COMPAT); //Force the compat mode + legacySerialHandler(currentSecondaryCommand, CANSerial, serialSecondaryStatusFlag); + break; + + case 'd': // Send a CRC32 hash of a given page + legacySerialHandler(currentSecondaryCommand, CANSerial, serialSecondaryStatusFlag); + break; case 'G': // this is the reply command sent by the Can interface - byte destcaninchannel; + serialSecondaryStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; + byte destcaninchannel; if (CANSerial.available() >= 9) { - canCmdPending = false; + serialSecondaryStatusFlag = SERIAL_INACTIVE; cancmdfail = CANSerial.read(); //0 == fail, 1 == good. destcaninchannel = CANSerial.read(); // the input channel that requested the data value if (cancmdfail != 0) @@ -94,12 +108,7 @@ void secondserial_Command(void) else{} //continue as command request failed and/or data/device was not available } - else - { - canCmdPending = true; - } - - break; + break; case 'k': //placeholder for new can interface (toucan etc) commands @@ -128,37 +137,19 @@ void secondserial_Command(void) break; case 'n': // sends the bytes of realtime values from the NEW CAN list - sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, SERIAL_PORT_SECONDARY); //send values to serial3 - break; + sendValues(0, NEW_CAN_PACKET_SIZE, 0x32, CANSerial); //send values to serial3 + break; + + case 'p': + legacySerialHandler(currentSecondaryCommand, CANSerial, serialSecondaryStatusFlag); + break; + + case 'Q': // send code version + legacySerialHandler(currentSecondaryCommand, CANSerial, serialSecondaryStatusFlag); + break; case 'r': //New format for the optimised OutputChannels over CAN - byte Cmd; - if (CANSerial.available() >= 6) - { - CANSerial.read(); //Read the $tsCanId - Cmd = CANSerial.read(); - - uint16_t offset, length; - if( (Cmd == 0x30) || ( (Cmd >= 0x40) && (Cmd <0x50) ) ) //Send output channels command 0x30 is 48dec, 0x40(64dec)-0x4F(79dec) are external can request - { - byte tmp; - tmp = CANSerial.read(); - offset = word(CANSerial.read(), tmp); - tmp = CANSerial.read(); - length = word(CANSerial.read(), tmp); - sendValues(offset, length,Cmd, SERIAL_PORT_SECONDARY); - canCmdPending = false; - //Serial.print(Cmd); - } - else - { - //No other r/ commands should be called - } - } - else - { - canCmdPending = true; - } + legacySerialHandler(currentSecondaryCommand, CANSerial, serialSecondaryStatusFlag); break; case 's': // send the "a" stream code version @@ -166,17 +157,10 @@ void secondserial_Command(void) break; case 'S': // send code version - CANSerial.print(F("Speeduino 2019.08-ser")); - break; + if(configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_MSDROID) { legacySerialHandler('Q', CANSerial, serialSecondaryStatusFlag); } //Note 'Q', this is a workaround for msDroid + else { legacySerialHandler(currentSecondaryCommand, CANSerial, serialSecondaryStatusFlag); } - case 'Q': // send code version - //for (unsigned int revn = 0; revn < sizeof( TSfirmwareVersion) - 1; revn++) - for (unsigned int revn = 0; revn < 10 - 1; revn++) - { - CANSerial.write( TSfirmwareVersion[revn]); - } - //Serial3.print("speeduino 201609-dev"); - break; + break; case 'Z': //dev use break; diff --git a/speeduino/comms.cpp b/speeduino/comms.cpp index 6d7087ab..9b99f316 100644 --- a/speeduino/comms.cpp +++ b/speeduino/comms.cpp @@ -527,7 +527,7 @@ void serialTransmit(void) switch (serialStatusFlag) { case SERIAL_TRANSMIT_INPROGRESS_LEGACY: - sendValues(logItemsTransmitted, inProgressLength, SEND_OUTPUT_CHANNELS, SERIAL_PORT_PRIMARY); + sendValues(logItemsTransmitted, inProgressLength, SEND_OUTPUT_CHANNELS, Serial); break; case SERIAL_TRANSMIT_TOOTH_INPROGRESS: diff --git a/speeduino/comms_legacy.cpp b/speeduino/comms_legacy.cpp index adb83653..fff73439 100644 --- a/speeduino/comms_legacy.cpp +++ b/speeduino/comms_legacy.cpp @@ -67,31 +67,17 @@ void legacySerialCommand(void) break; case 'A': // send x bytes of realtime values - sendValues(0, LOG_ENTRY_SIZE, 0x31, SERIAL_PORT_PRIMARY); //send values to serial0 + sendValues(0, LOG_ENTRY_SIZE, 0x31, Serial); //send values to serial0 firstCommsRequest = false; break; case 'b': // New EEPROM burn command to only burn a single page at a time - serialStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; - - if (Serial.available() >= 2) - { - Serial.read(); //Ignore the first table value, it's always 0 - writeConfig(Serial.read()); - serialStatusFlag = SERIAL_INACTIVE; - } + legacySerialHandler(currentCommand, Serial, serialStatusFlag); break; case 'B': // AS above but for the serial compatibility mode. - serialStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; BIT_SET(currentStatus.status4, BIT_STATUS4_COMMS_COMPAT); //Force the compat mode - - if (Serial.available() >= 2) - { - Serial.read(); //Ignore the first table value, it's always 0 - writeConfig(Serial.read()); - serialStatusFlag = SERIAL_INACTIVE; - } + legacySerialHandler(currentCommand, Serial, serialStatusFlag); break; case 'C': // test communications. This is used by Tunerstudio to see whether there is an ECU on a given serial port @@ -286,8 +272,7 @@ void legacySerialCommand(void) break; case 'Q': // send code version - //Serial.print(F("speeduino 202305")); - Serial.print(F("speeduino 202306-dev")); + legacySerialHandler(currentCommand, Serial, serialStatusFlag); break; case 'r': //New format for the optimised OutputChannels @@ -309,7 +294,7 @@ void legacySerialCommand(void) if(cmd == 0x30) //Send output channels command 0x30 is 48dec { - sendValues(offset, length, cmd, SERIAL_PORT_PRIMARY); + sendValues(offset, length, cmd, Serial); } else { @@ -319,8 +304,7 @@ void legacySerialCommand(void) break; case 'S': // send code version - //Serial.print(F("Speeduino 2023.05")); - Serial.print(F("Speeduino 2023.06-dev")); + legacySerialHandler(currentCommand, Serial, serialStatusFlag); //Send the bootloader capabilities currentStatus.secl = 0; //This is required in TS3 due to its stricter timings break; @@ -557,6 +541,120 @@ void legacySerialCommand(void) } } +void legacySerialHandler(byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag) +{ + switch (cmd) + { + + case 'b': // New EEPROM burn command to only burn a single page at a time + targetStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; + + if (targetPort.available() >= 2) + { + targetPort.read(); //Ignore the first table value, it's always 0 + writeConfig(targetPort.read()); + targetStatusFlag = SERIAL_INACTIVE; + } + break; + + case 'B': // AS above but for the serial compatibility mode. + targetStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; + + if (targetPort.available() >= 2) + { + targetPort.read(); //Ignore the first table value, it's always 0 + writeConfig(targetPort.read()); + targetStatusFlag = SERIAL_INACTIVE; + } + break; + + case 'd': + targetStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; + + if (targetPort.available() >= 2) + { + targetPort.read(); //Ignore the first byte value, it's always 0 + uint32_t CRC32_val = calculatePageCRC32( targetPort.read() ); + + //Split the 4 bytes of the CRC32 value into individual bytes and send + targetPort.write( ((CRC32_val >> 24) & 255) ); + targetPort.write( ((CRC32_val >> 16) & 255) ); + targetPort.write( ((CRC32_val >> 8) & 255) ); + targetPort.write( (CRC32_val & 255) ); + + targetStatusFlag = SERIAL_INACTIVE; + } + break; + + case 'p': + targetStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; + + //6 bytes required: + //2 - Page identifier + //2 - offset + //2 - Length + if(targetPort.available() >= 6) + { + byte offset1, offset2, length1, length2; + int length; + byte tempPage; + + targetPort.read(); // First byte of the page identifier can be ignored. It's always 0 + tempPage = targetPort.read(); + //currentPage = 1; + offset1 = targetPort.read(); + offset2 = targetPort.read(); + valueOffset = word(offset2, offset1); + length1 = targetPort.read(); + length2 = targetPort.read(); + length = word(length2, length1); + for(int i = 0; i < length; i++) + { + targetPort.write( getPageValue(tempPage, valueOffset + i) ); + } + + targetStatusFlag = SERIAL_INACTIVE; + } + break; + + case 'Q': // send code version + targetPort.print(F("speeduino 202306-dev")); + break; + + case 'r': //New format for the optimised OutputChannels + targetStatusFlag = SERIAL_COMMAND_INPROGRESS_LEGACY; + byte cmd; + if (targetPort.available() >= 6) + { + targetPort.read(); //Read the $tsCanId + cmd = targetPort.read(); // read the command + + uint16_t offset, length; + byte tmp; + tmp = targetPort.read(); + offset = word(targetPort.read(), tmp); + tmp = targetPort.read(); + length = word(targetPort.read(), tmp); + + targetStatusFlag = SERIAL_INACTIVE; + + if(cmd == 0x30) //Send output channels command 0x30 is 48dec + { + sendValues(offset, length, cmd, targetPort); + } + else + { + //No other r/ commands are supported in legacy mode + } + } + break; + + case 'S': // send code version + targetPort.print(F("Speeduino 2023.06-dev")); + break; + } +} + /** Send a status record back to tuning/logging SW. * This will "live" information from @ref currentStatus struct. * @param offset - Start field number @@ -566,29 +664,32 @@ void legacySerialCommand(void) * 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, byte portNum) +void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &targetPort) { - if (portNum == SERIAL_PORT_SECONDARY) + if (&targetPort == &CANSerial) { serialSecondaryStatusFlag = SERIAL_TRANSMIT_INPROGRESS_LEGACY; //CAN serial - #if defined(CANSerial_AVAILABLE) - if (cmd == 0x30) - { - CANSerial.write("r"); //confirm cmd type - CANSerial.write(cmd); - } - else if (cmd == 0x31) - { - CANSerial.write("A"); // confirm command type - } - else if (cmd == 0x32) - { - CANSerial.write("n"); // confirm command type - CANSerial.write(cmd); // send command type , 0x32 (dec50) is ascii '0' - CANSerial.write(NEW_CAN_PACKET_SIZE); // send the packet size the receiving device should expect. - } - #endif + if( (configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_GENERIC) || (configPage9.secondarySerialProtocol == SECONDARY_SERIAL_PROTO_REALDASH)) + { + #if defined(CANSerial_AVAILABLE) + if (cmd == 0x30) + { + CANSerial.write("r"); //confirm cmd type + CANSerial.write(cmd); + } + else if (cmd == 0x31) + { + CANSerial.write("A"); // confirm command type + } + else if (cmd == 0x32) + { + CANSerial.write("n"); // confirm command type + CANSerial.write(cmd); // send command type , 0x32 (dec50) is ascii '0' + CANSerial.write(NEW_CAN_PACKET_SIZE); // send the packet size the receiving device should expect. + } + #endif + } } else { @@ -607,18 +708,13 @@ void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portNum) { bool bufferFull = false; - if (portNum == SERIAL_PORT_PRIMARY) + targetPort.write(getTSLogEntry(offset+x)); + + if( (&targetPort == &Serial) || (configPage9.secondarySerialProtocol != SECONDARY_SERIAL_PROTO_REALDASH) ) { - Serial.write(getTSLogEntry(offset+x)); - if(Serial.availableForWrite() < 1) { bufferFull = true; } + //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; } } - #if defined(CANSerial_AVAILABLE) - else if (portNum == SERIAL_PORT_SECONDARY) - { - CANSerial.write(getTSLogEntry(offset+x)); - //if(CANSerial.availableForWrite() < 1) { bufferFull = true; } //Real Dash does not like data requests being broken up into multiple sends, so this must be disabled for now. - } - #endif //Check whether the tx buffer still has space if(bufferFull == true) @@ -631,18 +727,17 @@ void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portNum) } - if (portNum == SERIAL_PORT_PRIMARY) + if (&targetPort == &Serial) { serialStatusFlag = SERIAL_INACTIVE; while(Serial.available()) { Serial.read(); } // Reset any flags that are being used to trigger page refreshes BIT_CLEAR(currentStatus.status3, BIT_STATUS3_VSS_REFRESH); } - else if(portNum == SERIAL_PORT_SECONDARY) + else if(&targetPort == &CANSerial) { serialSecondaryStatusFlag = SERIAL_INACTIVE; } - } diff --git a/speeduino/comms_legacy.h b/speeduino/comms_legacy.h index c6f8d4c2..b7260945 100644 --- a/speeduino/comms_legacy.h +++ b/speeduino/comms_legacy.h @@ -74,7 +74,8 @@ extern byte logItemsTransmitted; 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 sendValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portNum); +void legacySerialHandler(byte cmd, Stream &targetPort, SerialStatus &targetStatusFlag); +void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, Stream &targetPort); void sendValuesLegacy(void); void sendPage(void); void sendPageASCII(void); diff --git a/speeduino/globals.h b/speeduino/globals.h index 0491cfb6..5990d483 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -1118,6 +1118,9 @@ 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 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 uint8_t caninput_source_start_byte[16]; //u08 [15] array holds the start byte number(value of 0-7)