Skip to content

Commit

Permalink
Add option for TunerStudio protocol on secondary serial
Browse files Browse the repository at this point in the history
  • Loading branch information
noisymime committed Aug 23, 2024
1 parent a727eb5 commit a9642f4
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 243 deletions.
3 changes: 2 additions & 1 deletion reference/speeduino.ini
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,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:6], "Generic (Fixed List)". "Generic (ini File)". "CAN", "msDroid", "Real Dash", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
secondarySerialProtocol = bits, U08, 0, [3:6], "Generic (Fixed List)". "Generic (ini File)". "CAN", "msDroid", "Real Dash", "Tuner Studio", "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"
Expand Down Expand Up @@ -3924,6 +3924,7 @@ menuDialog = main
topicHelp = "http://wiki.speeduino.com/en/Secondary_Serial_IO_interface"
field = "Enable Second Serial", enable_secondarySerial
field = "Second Serial protocol", secondarySerialProtocol, { enable_secondarySerial }
field = "#NOTE: When the TunerStudio protocol is selected, the primary and secondary serial connections cannot be used simultaneously", { } , { }, { secondarySerialProtocol == 5 }
#if mcu_teensy
field = "Enable Internal Canbus", enable_intcan
#elif mcu_stm32
Expand Down
39 changes: 19 additions & 20 deletions speeduino/comms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ static uint32_t SDreadCompletedSectors = 0;
#endif
static uint8_t serialPayload[SERIAL_BUFFER_SIZE]; //!< Serial payload buffer
static uint16_t serialPayloadLength = 0; //!< How many bytes in serialPayload were received or sent
Stream* pPrimarySerial;

#if defined(CORE_AVR)
#pragma GCC push_options
Expand All @@ -120,7 +121,7 @@ static inline bool isRxTimeout(void) {
*/
void flushRXbuffer(void)
{
while (Serial.available() > 0) { Serial.read(); }
while (primarySerial.available() > 0) { primarySerial.read(); }
}

/** @brief Reverse the byte order of a uint32_t
Expand All @@ -141,9 +142,9 @@ static __attribute__((noinline)) uint32_t reverse_bytes(uint32_t i)
void writeByteReliableBlocking(byte value) {
// Some platforms (I'm looking at you Teensy 3.5) do not mimic the Arduino 1.0
// contract which synchronously blocks.
// https://github.com/PaulStoffregen/cores/blob/master/teensy3/usb_serial.c#L215
while (!Serial.availableForWrite()) { /* Wait for the buffer to free up space */ }
Serial.write(value);
// https://github.com/PaulStoffregen/cores/blob/master/teensy3/usb_primarySerial.c#L215
while (!primarySerial.availableForWrite()) { /* Wait for the buffer to free up space */ }
primarySerial.write(value);
}

// ====================================== Multibyte Primitive Type IO Support =============================
Expand All @@ -155,8 +156,8 @@ static void readSerialTimeout(char *buffer, size_t length) {
// Teensy 3.5: Serial.available() should only be used as a boolean test
// See https://www.pjrc.com/teensy/td_serial.html#singlebytepackets
while (length>0U) {
if (Serial.available()!=0) {
buffer[--length] =(byte)Serial.read();
if (primarySerial.available()!=0) {
buffer[--length] =(byte)primarySerial.read();
} else if(isRxTimeout()) {
return;
} else { /* MISRA - no-op */ }
Expand Down Expand Up @@ -214,9 +215,9 @@ static uint16_t writeNonBlocking(const byte *buffer, size_t length)
uint16_t bytesTransmitted = 0;

while (bytesTransmitted<length
&& Serial.availableForWrite() != 0
&& primarySerial.availableForWrite() != 0
// Just in case
&& Serial.write(buffer[bytesTransmitted]) == 1)
&& primarySerial.write(buffer[bytesTransmitted]) == 1)
{
bytesTransmitted++;
}
Expand Down Expand Up @@ -470,11 +471,11 @@ void serialReceive(void)
return;
}

if (Serial.available()!=0 && serialStatusFlag == SERIAL_INACTIVE)
if (primarySerial.available()!=0 && serialStatusFlag == SERIAL_INACTIVE)
{
//New command received
//Need at least 2 bytes to read the length of the command
char highByte = (char)Serial.peek();
char highByte = (char)primarySerial.peek();

//Check if the command is legacy using the call/response mechanism
if(highByte == 'F')
Expand All @@ -501,11 +502,11 @@ void serialReceive(void)
}

//If there is a serial receive in progress, read as much from the buffer as possible or until we receive all bytes
while( (Serial.available() > 0) && (serialStatusFlag == SERIAL_RECEIVE_INPROGRESS) )
while( (primarySerial.available() > 0) && (serialStatusFlag == SERIAL_RECEIVE_INPROGRESS) )
{
if (serialBytesRxTx < serialPayloadLength )
{
serialPayload[serialBytesRxTx] = (byte)Serial.read();
serialPayload[serialBytesRxTx] = (byte)primarySerial.read();
++serialBytesRxTx;
}
else
Expand Down Expand Up @@ -822,8 +823,6 @@ void processSerialCommand(void)
}
serialPayload[payloadIndex] = lowByte(SDcurrentDirChunk);
serialPayload[payloadIndex + 1] = highByte(SDcurrentDirChunk);
//Serial.print("Index:");
//Serial.print(payloadIndex);

sendSerialPayloadNonBlocking(payloadIndex + 2);
}
Expand Down Expand Up @@ -890,7 +889,7 @@ void processSerialCommand(void)
{
loadO2CalibrationChunk(offset, calibrationLength);
sendReturnCodeMsg(SERIAL_RC_OK);
Serial.flush(); //This is safe because engine is assumed to not be running during calibration
primarySerial.flush(); //This is safe because engine is assumed to not be running during calibration
}
else if(cmd == IAT_CALIBRATION_PAGE)
{
Expand All @@ -911,16 +910,16 @@ void processSerialCommand(void)
if (resetControl != RESET_CONTROL_DISABLED)
{
#ifndef SMALL_FLASH_MODE
if (serialStatusFlag == SERIAL_INACTIVE) { Serial.println(F("Comms halted. Next byte will reset the Arduino.")); }
if (serialStatusFlag == SERIAL_INACTIVE) { primarySerial.println(F("Comms halted. Next byte will reset the Arduino.")); }
#endif

while (Serial.available() == 0) { }
while (primarySerial.available() == 0) { }
digitalWrite(pinResetControl, LOW);
}
else
{
#ifndef SMALL_FLASH_MODE
if (serialStatusFlag == SERIAL_INACTIVE) { Serial.println(F("Reset control is currently disabled.")); }
if (serialStatusFlag == SERIAL_INACTIVE) { primarySerial.println(F("Reset control is currently disabled.")); }
#endif
}
break;
Expand Down Expand Up @@ -1096,7 +1095,7 @@ void sendToothLog(void)
for (; logItemsTransmitted < TOOTH_LOG_SIZE; logItemsTransmitted++)
{
//Check whether the tx buffer still has space
if(Serial.availableForWrite() < 4)
if(primarySerial.availableForWrite() < 4)
{
//tx buffer is full. Store the current state so it can be resumed later
serialStatusFlag = SERIAL_TRANSMIT_TOOTH_INPROGRESS;
Expand Down Expand Up @@ -1149,7 +1148,7 @@ void sendCompositeLog(void)
for (; logItemsTransmitted < TOOTH_LOG_SIZE; logItemsTransmitted++)
{
//Check whether the tx buffer still has space
if((uint16_t)Serial.availableForWrite() < sizeof(toothHistory[logItemsTransmitted])+sizeof(compositeLogHistory[logItemsTransmitted]))
if((uint16_t)primarySerial.availableForWrite() < sizeof(toothHistory[logItemsTransmitted])+sizeof(compositeLogHistory[logItemsTransmitted]))
{
//tx buffer is full. Store the current state so it can be resumed later
serialStatusFlag = SERIAL_TRANSMIT_COMPOSITE_INPROGRESS;
Expand Down
3 changes: 3 additions & 0 deletions speeduino/comms.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#define TABLE_BLOCKING_FACTOR 64
#endif

extern Stream *pPrimarySerial;
#define primarySerial (*pPrimarySerial)

/**
* @brief The serial receive pump. Should be called whenever the serial port
* has data available to read.
Expand Down
Loading

0 comments on commit a9642f4

Please sign in to comment.