diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 76faeb74..844cd678 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -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 } diff --git a/speeduino/cancomms.ino b/speeduino/cancomms.ino index 594c0727..f2a18f3a 100644 --- a/speeduino/cancomms.ino +++ b/speeduino/cancomms.ino @@ -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 diff --git a/speeduino/comms.h b/speeduino/comms.h index ba0168f4..aefcd103 100644 --- a/speeduino/comms.h +++ b/speeduino/comms.h @@ -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); diff --git a/speeduino/comms.ino b/speeduino/comms.ino index 11cd63c8..8405ae5f 100644 --- a/speeduino/comms.ino +++ b/speeduino/comms.ino @@ -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'++ + 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", . 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