Move to TS optimised serial comms model + many minor serial improvements

This commit is contained in:
Josh Stewart 2017-04-22 23:31:13 +10:00
parent 71e963e196
commit 4380f8b0d5
4 changed files with 105 additions and 67 deletions

View File

@ -1847,7 +1847,8 @@ cmdtestspk450dc = "E\x03\x0C"
deadValue = { 0 } ; Convenient unchanging value.
ochGetCommand = "A"
;ochGetCommand = "A"
ochGetCommand = "r\$tsCanId\x07%2o%2c"
ochBlockSize = 41
@ -1935,9 +1936,9 @@ cmdtestspk450dc = "E\x03\x0C"
throttle = { tps }, "%"
;cycleTime = { 60000.0 / rpm * (2.0-twoStroke) }
cycleTime = { 60000.0 / rpm }
cycleTime = { rpm ? ( 60000.0 / rpm ) : 0 }
;nSquirts = { nCylinders/divider }
dutyCycle = { 100.0*pulseWidth/cycleTime }
dutyCycle = { rpm ? ( 100.0*pulseWidth/cycleTime ) : 0 }
boostCutOut = { boostCutFuel || boostCutSpark }
lambda = { afr / stoich }

View File

@ -22,7 +22,7 @@ void canCommand()
switch (Serial3.read())
{
case 'A': // sends the bytes of realtime values
sendValues(packetSize,3); //send values to serial3
sendValues(0, packetSize,3); //send values to serial3
break;
case 'G': // this is the reply command sent by the Can interface

View File

@ -17,6 +17,8 @@
byte currentPage = 1;//Not the same as the speeduino config page numbers
boolean isMap = true;
unsigned long requestCount = 0; //The number of times the A command has been issued
byte currentCommand;
bool cmdPending = false;
byte cmdGroup = 0;
byte cmdValue = 0;
int cmdCombined = 0; //the cmdgroup as high byte and cmdvalue as low byte
@ -37,7 +39,7 @@ const char pageTitles[] PROGMEM //This is being stored in the avr flash instead
};
void command();//This is the heart of the Command Line Interpeter. All that needed to be done was to make it human readable.
void sendValues(int packetlength, byte portnum);
void sendValues(uint16_t offset, uint16_t packetlength, byte portnum);
void receiveValue(int offset, byte newValue);
void saveConfig();
void sendPage(bool useChar);

View File

@ -15,12 +15,16 @@ A detailed description of each call can be found at: http://www.msextra.com/doc/
void command()
{
switch (Serial.read())
if (!cmdPending) { currentCommand = Serial.read(); }
switch (currentCommand)
{
case 'A': // send x bytes of realtime values
sendValues(packetSize, 0); //send values to serial0
sendValues(0, packetSize, 0); //send values to serial0
break;
case 'B': // Burn current values to eeprom
writeConfig();
break;
@ -30,13 +34,15 @@ void command()
break;
case 'E': // receive command button commands
while (Serial.available() == 0) { }
cmdPending = true;
if(Serial.available() < 2) { return; }
cmdGroup = Serial.read();
while (Serial.available() == 0) { }
cmdValue = Serial.read();
cmdCombined = word(cmdGroup, cmdValue);
if (currentStatus.RPM == 0) { commandButtons(); }
cmdPending = false;
break;
case 'L': // List the contents of current page in human readable form
@ -49,8 +55,9 @@ void command()
case 'P': // set the current page
//A 2nd byte of data is required after the 'P' specifying the new page number.
//This loop should never need to run as the byte should already be in the buffer, but is here just in case
while (Serial.available() == 0) { }
cmdPending = true;
if (Serial.available() == 0) { return; }
currentPage = Serial.read();
if (currentPage >= '0') {//This converts the ascii number char into binary
currentPage -= '0';
@ -61,10 +68,7 @@ void command()
else {
isMap = false;
}
break;
case 'R': // send 39 bytes of realtime values
sendValues(39,0);
cmdPending = false;
break;
case 'F': // send serial protocol version
@ -85,24 +89,25 @@ void command()
break;
case 'W': // receive new VE obr constant at 'W'+<offset>+<newbyte>
cmdPending = true;
int valueOffset; //cannot use offset as a variable name, it is a reserved word for several teensy libraries
while (Serial.available() == 0) { }
if (isMap)
{
if(Serial.available()< 3) { return; } // 1 additional byte is required on the MAP pages which are larger than 255 bytes
byte offset1, offset2;
offset1 = Serial.read();
while (Serial.available() == 0) { }
offset2 = Serial.read();
valueOffset = word(offset2, offset1);
}
else
{
if(Serial.available()< 2) { return; }
valueOffset = Serial.read();
}
while (Serial.available() == 0) { }
receiveValue(valueOffset, Serial.read());
cmdPending = false;
break;
case 't': // receive new Calibration info. Command structure: "t", <tble_idx> <data array>. This is an MS2/Extra command, NOT part of MS1 spec
@ -160,10 +165,33 @@ void command()
sendToothLog(false); //Sends tooth log values as ints
break;
case 'r': //Send 256 tooth log entries to a terminal emulator
case 'z': //Send 256 tooth log entries to a terminal emulator
sendToothLog(true); //Sends tooth log values as chars
break;
case 'r': //New format for the optimised OutputChannels
cmdPending = true;
byte cmd;
if (Serial.available() < 6) { return; }
Serial.read(); //Read the $tsCanId
cmd = Serial.read();
uint16_t offset, length;
if(cmd == 0x07) //Send output channels command
{
byte tmp;
tmp = Serial.read();
offset = word(Serial.read(), tmp);
tmp = Serial.read();
length = word(Serial.read(), tmp);
sendValues(offset, length, 0);
}
else
{
//No other r/ commands should be called
}
cmdPending = false;
break;
case '?':
@ -208,19 +236,21 @@ void command()
/*
This function returns the current values of a fixed group of variables
*/
void sendValues(int packetlength, byte portNum)
//void sendValues(int packetlength, byte portNum)
void sendValues(uint16_t offset, uint16_t packetLength, byte portNum)
{
byte response[packetlength];
byte fullStatus[packetSize];
byte response[packetLength];
if (portNum == 3)
{
//CAN serial
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //ATmega2561 does not have Serial3
Serial3.write("A"); //confirm cmd type
Serial3.write(packetlength); //confirm no of byte to be sent
Serial3.write(packetLength); //confirm no of byte to be sent
#elif defined(CORE_STM32)
Serial2.write("A"); //confirm cmd type
Serial2.write(packetlength); //confirm no of byte to be sent
Serial2.write(packetLength); //confirm no of byte to be sent
#endif
}
else
@ -231,62 +261,67 @@ void sendValues(int packetlength, byte portNum)
currentStatus.spark ^= (-currentStatus.hasSync ^ currentStatus.spark) & (1 << BIT_SPARK_SYNC); //Set the sync bit of the Spark variable to match the hasSync variable
response[0] = currentStatus.secl; //secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0)
response[1] = currentStatus.squirt; //Squirt Bitfield
response[2] = currentStatus.engine; //Engine Status Bitfield
response[3] = (byte)(divu100(currentStatus.dwell)); //Dwell in ms * 10
response[4] = (byte)(currentStatus.MAP >> 1); //map value is divided by 2
response[5] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //mat
response[6] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //Coolant ADC
response[7] = currentStatus.tpsADC; //TPS (Raw 0-255)
response[8] = currentStatus.battery10; //battery voltage
response[9] = currentStatus.O2; //O2
response[10] = currentStatus.egoCorrection; //Exhaust gas correction (%)
response[11] = currentStatus.iatCorrection; //Air temperature Correction (%)
response[12] = currentStatus.wueCorrection; //Warmup enrichment (%)
response[13] = lowByte(currentStatus.RPM); //rpm HB
response[14] = highByte(currentStatus.RPM); //rpm LB
response[15] = currentStatus.TAEamount; //acceleration enrichment (%)
response[16] = currentStatus.baro; //Barometer value
response[17] = currentStatus.corrections; //Total GammaE (%)
response[18] = currentStatus.VE; //Current VE 1 (%)
response[19] = currentStatus.afrTarget;
response[20] = (byte)(currentStatus.PW1 / 100); //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
response[21] = currentStatus.tpsDOT; //TPS DOT
response[22] = currentStatus.advance;
response[23] = currentStatus.TPS; // TPS (0% to 100%)
fullStatus[0] = currentStatus.secl; //secl is simply a counter that increments each second. Used to track unexpected resets (Which will reset this count to 0)
fullStatus[1] = currentStatus.squirt; //Squirt Bitfield
fullStatus[2] = currentStatus.engine; //Engine Status Bitfield
fullStatus[3] = (byte)(divu100(currentStatus.dwell)); //Dwell in ms * 10
fullStatus[4] = (byte)(currentStatus.MAP >> 1); //map value is divided by 2
fullStatus[5] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //mat
fullStatus[6] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //Coolant ADC
fullStatus[7] = currentStatus.tpsADC; //TPS (Raw 0-255)
fullStatus[8] = currentStatus.battery10; //battery voltage
fullStatus[9] = currentStatus.O2; //O2
fullStatus[10] = currentStatus.egoCorrection; //Exhaust gas correction (%)
fullStatus[11] = currentStatus.iatCorrection; //Air temperature Correction (%)
fullStatus[12] = currentStatus.wueCorrection; //Warmup enrichment (%)
fullStatus[13] = lowByte(currentStatus.RPM); //rpm HB
fullStatus[14] = highByte(currentStatus.RPM); //rpm LB
fullStatus[15] = currentStatus.TAEamount; //acceleration enrichment (%)
fullStatus[16] = currentStatus.baro; //Barometer value
fullStatus[17] = currentStatus.corrections; //Total GammaE (%)
fullStatus[18] = currentStatus.VE; //Current VE 1 (%)
fullStatus[19] = currentStatus.afrTarget;
fullStatus[20] = (byte)(currentStatus.PW1 / 100); //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
fullStatus[21] = currentStatus.tpsDOT; //TPS DOT
fullStatus[22] = currentStatus.advance;
fullStatus[23] = currentStatus.TPS; // TPS (0% to 100%)
//Need to split the int loopsPerSecond value into 2 bytes
response[24] = lowByte(currentStatus.loopsPerSecond);
response[25] = highByte(currentStatus.loopsPerSecond);
fullStatus[24] = lowByte(currentStatus.loopsPerSecond);
fullStatus[25] = highByte(currentStatus.loopsPerSecond);
//The following can be used to show the amount of free memory
currentStatus.freeRAM = freeRam();
response[26] = lowByte(currentStatus.freeRAM); //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF);
response[27] = highByte(currentStatus.freeRAM);
fullStatus[26] = lowByte(currentStatus.freeRAM); //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF);
fullStatus[27] = highByte(currentStatus.freeRAM);
response[28] = currentStatus.batCorrection; //Battery voltage correction (%)
response[29] = currentStatus.spark; //Spark related bitfield
response[30] = currentStatus.O2_2; //O2
fullStatus[28] = currentStatus.batCorrection; //Battery voltage correction (%)
fullStatus[29] = currentStatus.spark; //Spark related bitfield
fullStatus[30] = currentStatus.O2_2; //O2
//rpmDOT must be sent as a signed integer
response[31] = lowByte(currentStatus.rpmDOT);
response[32] = highByte(currentStatus.rpmDOT);
fullStatus[31] = lowByte(currentStatus.rpmDOT);
fullStatus[32] = highByte(currentStatus.rpmDOT);
response[33] = currentStatus.ethanolPct; //Flex sensor value (or 0 if not used)
response[34] = currentStatus.flexCorrection; //Flex fuel correction (% above or below 100)
response[35] = currentStatus.flexIgnCorrection; //Ignition correction (Increased degrees of advance) for flex fuel
response[36] = getNextError();
response[37] = currentStatus.boostTarget;
response[38] = currentStatus.boostDuty;
response[39] = currentStatus.idleLoad;
response[40] = currentStatus.testOutputs;
fullStatus[33] = currentStatus.ethanolPct; //Flex sensor value (or 0 if not used)
fullStatus[34] = currentStatus.flexCorrection; //Flex fuel correction (% above or below 100)
fullStatus[35] = currentStatus.flexIgnCorrection; //Ignition correction (Increased degrees of advance) for flex fuel
fullStatus[36] = getNextError();
fullStatus[37] = currentStatus.boostTarget;
fullStatus[38] = currentStatus.boostDuty;
fullStatus[39] = currentStatus.idleLoad;
fullStatus[40] = currentStatus.testOutputs;
for(byte x=0; x<packetLength; x++)
{
response[x] = fullStatus[offset+x];
}
//cli();
if (portNum == 0) { Serial.write(response, (size_t)packetlength); }
if (portNum == 0) { Serial.write(response, (size_t)packetLength); }
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //ATmega2561 does not have Serial3
else if (portNum == 3) { Serial3.write(response, (size_t)packetlength); }
else if (portNum == 3) { Serial3.write(response, (size_t)packetLength); }
#elif defined(CORE_STM32)
else if (portNum == 3) { Serial2.write(response, (size_t)packetlength); }
else if (portNum == 3) { Serial2.write(response, (size_t)packetLength); }
#endif
//sei();
return;