From 7272b0e069cb4a10f83a450c8b019cd2b797ddae Mon Sep 17 00:00:00 2001 From: ConnerMcLaughlin Date: Sat, 10 Oct 2015 07:43:45 -0500 Subject: [PATCH 1/4] Start of basic CLI for TS alts --- comms.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/comms.h b/comms.h index ae5f7fb..a9f57fb 100644 --- a/comms.h +++ b/comms.h @@ -10,13 +10,24 @@ #define iacPage 7 #define boostvvtPage 8 -byte currentPage; - +byte currentPage = 1; +boolean isMap = true; +const char pageTitles[] PROGMEM + { + "\nVolumetric Efficiancy Map\0" + "\nPage 1 Config\0" + "\nIgnition Map\0" + "\nPage 2 Config\0" + "\nAir/Fuel Ratio Map\0" + "\nPage 3 Config\0" + "\nPage 4 Config" + }; + void command(); void sendValues(); void receiveValue(int offset, byte newValue); void saveConfig(); -void sendPage(); +void sendPage(bool useChar); void receiveCalibration(byte tableID); void sendToothLog(bool useChar); void testComm(); From cd5fb9a30e3d9fed2103215aa28054a6f9fec526 Mon Sep 17 00:00:00 2001 From: ConnerMcLaughlin Date: Sat, 10 Oct 2015 07:46:24 -0500 Subject: [PATCH 2/4] Start of CLI for TS alts --- comms.ino | 399 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 304 insertions(+), 95 deletions(-) diff --git a/comms.ino b/comms.ino index 66fd035..b787252 100644 --- a/comms.ino +++ b/comms.ino @@ -27,13 +27,24 @@ void command() case 'C': // test communications. This is used by Tunerstudio to see whether there is an ECU on a given serial port testComm(); + break; + + case 'L': + sendPage(true); break; - + + case 'N': + Serial.println(); + break; + 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) { } currentPage = Serial.read(); + if(currentPage >= '0') {currentPage -= '0';} + if(currentPage == veMapPage || currentPage == ignMapPage || currentPage == afrMapPage) {isMap = true;} + else{isMap = false;} break; case 'R': // send 39 bytes of realtime values @@ -50,14 +61,14 @@ void command() break; case 'V': // send VE table and constants - sendPage(); + sendPage(false); break; case 'W': // receive new VE or constant at 'W'++ int offset; while (Serial.available() == 0) { } - if(currentPage == veMapPage || currentPage == ignMapPage || currentPage == afrMapPage ) + if(isMap) { byte offset1, offset2; offset1 = Serial.read(); @@ -94,29 +105,28 @@ void command() digitalWrite(pinInjector1, LOW); digitalWrite(pinInjector2, LOW); return; - - Serial.println("Coolant"); + Serial.println(F("Coolant")); for(int x=0; x+++\n\n" + "===List of Commands===\n\n" + "A - Displays 31 bytes of currentStatus values in binary (live data)\n" + "B - Burn current map and configPage values to eeprom\n" + "C - Test COM port. Used by Tunerstudio to see whether an ECU is on a given serial \n" + " port. Returns a binary number.\n" + "L - Displays map page (aka table) or configPage values. Use P to change page (not \n" + " every page is a map)\n" + "N - Print new line.\n" + "P - Set current page. Syntax: P+\n" + "R - Same as A command\n" + "S - Display signature number\n" + "Q - Same as S command\n" + "V - Display map or configPage values in binary\n" + "W - Set one byte in map or configPage. Expects binary parameters. \n" + " Syntax: W++\n" + "t - Set calibration values. Expects binary parameters. Table index is either 0, \n" + " 1, or 2. Syntax: t++++\n" + "Z - Display calibration values\n" + "T - Displays 256 tooth log entries in binary\n" + "r - Displays 256 tooth log entries\n" + "? - Displays this help page" + )); + break; + + default: + break; } } @@ -150,8 +194,8 @@ void sendValues(int length) 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[3] = 0x00; //baro + response[4] = currentStatus.MAP; //map 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) @@ -192,7 +236,7 @@ void sendValues(int length) void receiveValue(int offset, byte newValue) { - byte* pnt_configPage; + void* pnt_configPage; switch (currentPage) { @@ -208,7 +252,7 @@ void receiveValue(int offset, byte newValue) if (offset < 272) { //X Axis - fuelTable.axisX[(offset-256)] = ((int)(newValue) * 100); //The RPM values sent by tunerstudio are divided by 100, need to multiple it back by 100 to make it correct + fuelTable.axisX[(offset-256)] = ((int)(newValue) * 100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct } else { @@ -221,11 +265,11 @@ void receiveValue(int offset, byte newValue) break; case veSetPage: - pnt_configPage = (byte *)&configPage1; //Setup a pointer to the relevant config page + pnt_configPage = &configPage1; //Setup a pointer to the relevant config page //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size if( offset < page_size) { - *(pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages + *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages } break; @@ -241,7 +285,7 @@ void receiveValue(int offset, byte newValue) if (offset < 272) { //X Axis - ignitionTable.axisX[(offset-256)] = (int)(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiple it back by 100 to make it correct + ignitionTable.axisX[(offset-256)] = (int)(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct } else { @@ -253,11 +297,11 @@ void receiveValue(int offset, byte newValue) } case ignSetPage: - pnt_configPage = (byte *)&configPage2; + pnt_configPage = &configPage2; //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size if( offset < page_size) { - *(pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages + *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages } break; @@ -273,7 +317,7 @@ void receiveValue(int offset, byte newValue) if (offset < 272) { //X Axis - afrTable.axisX[(offset-256)] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct + afrTable.axisX[(offset-256)] = int(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiply it back by 100 to make it correct } else { @@ -286,23 +330,22 @@ void receiveValue(int offset, byte newValue) } case afrSetPage: - pnt_configPage = (byte *)&configPage3; + pnt_configPage = &configPage3; //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size if( offset < page_size) { - *(pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages + *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages } break; case iacPage: //Idle Air Control settings page (Page 4) - pnt_configPage = (byte *)&configPage4; + pnt_configPage = &configPage4; //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size if( offset < page_size) { - *(pnt_configPage + (byte)offset) = newValue; + *((byte *)pnt_configPage + (byte)offset) = newValue; } break; - case boostvvtPage: //Boost and VVT maps (8x8) if (offset < 64) //New value is part of the boost map { @@ -337,7 +380,6 @@ void receiveValue(int offset, byte newValue) vvtTable.axisY[(7-offset)] = int(newValue); return; } - default: break; } @@ -348,104 +390,186 @@ sendPage() packs the data within the current page (As set with the 'P' command) into a buffer and sends it. Note that some translation of the data is required to lay it out in the way Megasqurit / TunerStudio expect it */ -void sendPage() +void sendPage(bool useChar) { - byte* pnt_configPage; - + void* pnt_configPage; + struct table3D currentTable; + byte currentTitleIndex=0; + switch (currentPage) { case veMapPage: { - //Need to perform a translation of the values[MAP/TPS][RPM] into the MS expected format - //MS format has origin (0,0) in the bottom left corner, we use the top left for efficiency reasons - byte response[map_page_size]; - - for(int x=0;x<256;x++) { response[x] = fuelTable.values[15-x/16][x%16]; } //This is slightly non-intuitive, but essentially just flips the table vertically (IE top line becomes the bottom line etc). Columns are unchanged - for(int x=256;x<272;x++) { response[x] = byte(fuelTable.axisX[(x-256)] / 100); } //RPM Bins for VE table (Need to be dvidied by 100) - for(int y=272;y<288;y++) { response[y] = byte(fuelTable.axisY[15-(y-272)]); } //MAP or TPS bins for VE table - Serial.write((byte *)&response, sizeof(response)); - break; + currentTitleIndex = 0; + currentTable = fuelTable; + break; } case veSetPage: { - //All other bytes can simply be copied from the config table - byte response[page_size]; - - pnt_configPage = (byte *)&configPage1; //Create a pointer to Page 1 in memory - for(byte x=0; x Date: Tue, 13 Oct 2015 09:29:59 +1100 Subject: [PATCH 3/4] Formatting and minor fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For my own sanity I’ve cleaned up some of the formatting to match other files. Also added the MAP reading back in as it looks like this had gotten overwritten. --- comms.ino | 1132 +++++++++++++++++++++++++++-------------------------- 1 file changed, 583 insertions(+), 549 deletions(-) diff --git a/comms.ino b/comms.ino index b787252..74ef766 100644 --- a/comms.ino +++ b/comms.ino @@ -15,172 +15,178 @@ A detailed description of each call can be found at: http://www.msextra.com/doc/ void command() { - switch (Serial.read()) + switch (Serial.read()) { - case 'A': // send 22 bytes of realtime values - sendValues(22); - break; + case 'A': // send 22 bytes of realtime values + sendValues(22); + break; - case 'B': // Burn current values to eeprom - writeConfig(); - break; + case 'B': // Burn current values to eeprom + writeConfig(); + break; - case 'C': // test communications. This is used by Tunerstudio to see whether there is an ECU on a given serial port - testComm(); - break; - - case 'L': - sendPage(true); - break; - - case 'N': - Serial.println(); - break; - - 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) { } - currentPage = Serial.read(); - if(currentPage >= '0') {currentPage -= '0';} - if(currentPage == veMapPage || currentPage == ignMapPage || currentPage == afrMapPage) {isMap = true;} - else{isMap = false;} - break; + case 'C': // test communications. This is used by Tunerstudio to see whether there is an ECU on a given serial port + testComm(); + break; - case 'R': // send 39 bytes of realtime values - sendValues(39); - break; + case 'L': + sendPage(true); + break; - case 'S': // send code version - Serial.print(signature); - break; + case 'N': + Serial.println(); + break; - case 'Q': // send code version - Serial.print(signature); - //Serial.write("Speeduino_0_2"); - break; + 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) { } + currentPage = Serial.read(); + if (currentPage >= '0') { + currentPage -= '0'; + } + if (currentPage == veMapPage || currentPage == ignMapPage || currentPage == afrMapPage) { + isMap = true; + } + else { + isMap = false; + } + break; - case 'V': // send VE table and constants - sendPage(false); - break; + case 'R': // send 39 bytes of realtime values + sendValues(39); + break; - case 'W': // receive new VE or constant at 'W'++ - int offset; - while (Serial.available() == 0) { } - - if(isMap) - { + case 'S': // send code version + Serial.print(signature); + break; + + case 'Q': // send code version + Serial.print(signature); + //Serial.write("Speeduino_0_2"); + break; + + case 'V': // send VE table and constants + sendPage(false); + break; + + case 'W': // receive new VE or constant at 'W'++ + int offset; + while (Serial.available() == 0) { } + + if (isMap) + { byte offset1, offset2; offset1 = Serial.read(); while (Serial.available() == 0) { } offset2 = Serial.read(); offset = word(offset2, offset1); - } - else - { - offset = Serial.read(); - } - while (Serial.available() == 0) { } - - receiveValue(offset, Serial.read()); - break; + } + else + { + offset = Serial.read(); + } + while (Serial.available() == 0) { } - case 't': // receive new Calibration info. Command structure: "t", . This is an MS2/Extra command, NOT part of MS1 spec - byte tableID; - //byte canID; - - //The first 2 bytes sent represent the canID and tableID - while (Serial.available() == 0) { } - tableID = Serial.read(); //Not currently used for anything - - receiveCalibration(tableID); //Receive new values and store in memory - writeCalibration(); //Store received values in EEPROM + receiveValue(offset, Serial.read()); + break; - break; + case 't': // receive new Calibration info. Command structure: "t", . This is an MS2/Extra command, NOT part of MS1 spec + byte tableID; + //byte canID; - case 'Z': //Totally non-standard testing function. Will be removed once calibration testing is completed. This function takes 1.5kb of program space! :S - digitalWrite(pinInjector1, HIGH); - digitalWrite(pinInjector2, HIGH); - delay(20); - digitalWrite(pinInjector1, LOW); - digitalWrite(pinInjector2, LOW); - return; - Serial.println(F("Coolant")); - for(int x=0; x+++\n\n" - "===List of Commands===\n\n" - "A - Displays 31 bytes of currentStatus values in binary (live data)\n" - "B - Burn current map and configPage values to eeprom\n" - "C - Test COM port. Used by Tunerstudio to see whether an ECU is on a given serial \n" - " port. Returns a binary number.\n" - "L - Displays map page (aka table) or configPage values. Use P to change page (not \n" - " every page is a map)\n" - "N - Print new line.\n" - "P - Set current page. Syntax: P+\n" - "R - Same as A command\n" - "S - Display signature number\n" - "Q - Same as S command\n" - "V - Display map or configPage values in binary\n" - "W - Set one byte in map or configPage. Expects binary parameters. \n" - " Syntax: W++\n" - "t - Set calibration values. Expects binary parameters. Table index is either 0, \n" - " 1, or 2. Syntax: t++++\n" - "Z - Display calibration values\n" - "T - Displays 256 tooth log entries in binary\n" - "r - Displays 256 tooth log entries\n" - "? - Displays this help page" - )); - - break; + case 'Z': //Totally non-standard testing function. Will be removed once calibration testing is completed. This function takes 1.5kb of program space! :S + digitalWrite(pinInjector1, HIGH); + digitalWrite(pinInjector2, HIGH); + delay(20); + digitalWrite(pinInjector1, LOW); + digitalWrite(pinInjector2, LOW); + return; + Serial.println(F("Coolant")); + for (int x = 0; x < CALIBRATION_TABLE_SIZE; x++) + { + Serial.print(x); + Serial.print(", "); + Serial.println(cltCalibrationTable[x]); + } + Serial.println(F("Inlet temp")); + for (int x = 0; x < CALIBRATION_TABLE_SIZE; x++) + { + Serial.print(x); + Serial.print(", "); + Serial.println(iatCalibrationTable[x]); + } + Serial.println(F("O2")); + for (int x = 0; x < CALIBRATION_TABLE_SIZE; x++) + { + Serial.print(x); + Serial.print(", "); + Serial.println(o2CalibrationTable[x]); + } + Serial.println(F("WUE")); + for (int x = 0; x < 10; x++) + { + Serial.print(configPage2.wueBins[x]); + Serial.print(", "); + Serial.println(configPage1.wueValues[x]); + } + Serial.flush(); + break; - default: - break; - } + case 'T': //Send 256 tooth log entries to Tuner Studios tooth logger + sendToothLog(false); //Sends tooth log values as ints + break; + + case 'r': //Send 256 tooth log entries to a terminal emulator + sendToothLog(true); //Sends tooth log values as chars + break; + + case '?': + Serial.println + (F( + "\n" + "===Command Help===\n\n" + "All commands are single character and are concatenated with their parameters \n" + "without spaces. Some parameters are binary and cannot be entered through this \n" + "prompt by conventional means. \n" + "Syntax: +++\n\n" + "===List of Commands===\n\n" + "A - Displays 31 bytes of currentStatus values in binary (live data)\n" + "B - Burn current map and configPage values to eeprom\n" + "C - Test COM port. Used by Tunerstudio to see whether an ECU is on a given serial \n" + " port. Returns a binary number.\n" + "L - Displays map page (aka table) or configPage values. Use P to change page (not \n" + " every page is a map)\n" + "N - Print new line.\n" + "P - Set current page. Syntax: P+\n" + "R - Same as A command\n" + "S - Display signature number\n" + "Q - Same as S command\n" + "V - Display map or configPage values in binary\n" + "W - Set one byte in map or configPage. Expects binary parameters. \n" + " Syntax: W++\n" + "t - Set calibration values. Expects binary parameters. Table index is either 0, \n" + " 1, or 2. Syntax: t++++\n" + "Z - Display calibration values\n" + "T - Displays 256 tooth log entries in binary\n" + "r - Displays 256 tooth log entries\n" + "? - Displays this help page" + )); + + break; + + default: + break; + } } /* @@ -190,11 +196,11 @@ void sendValues(int length) { byte packetSize = 31; byte response[packetSize]; - + 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] = 0x00; //baro + response[3] = (byte)(divu100(currentStatus.dwell)); //Dwell in ms * 10 response[4] = currentStatus.MAP; //map response[5] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //mat response[6] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //Coolant ADC @@ -211,477 +217,497 @@ void sendValues(int length) response[17] = currentStatus.corrections; //Total GammaE (%) response[18] = currentStatus.VE; //Current VE 1 (%) response[19] = currentStatus.afrTarget; - response[20] = (byte)(currentStatus.PW / 100); //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS. + response[20] = (byte)(currentStatus.PW / 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%) //Need to split the int loopsPerSecond value into 2 bytes response[24] = lowByte(currentStatus.loopsPerSecond); response[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); - + response[28] = currentStatus.batCorrection; //Battery voltage correction (%) response[29] = (byte)(currentStatus.dwell / 100); response[30] = currentStatus.O2_2; //O2 Serial.write(response, (size_t)packetSize); //Serial.flush(); - return; + return; } void receiveValue(int offset, byte newValue) { - + void* pnt_configPage; - switch (currentPage) + switch (currentPage) { - case veMapPage: - if (offset < 256) //New value is part of the fuel map + case veMapPage: + if (offset < 256) //New value is part of the fuel map + { + fuelTable.values[15 - offset / 16][offset % 16] = newValue; + return; + } + else + { + //Check whether this is on the X (RPM) or Y (MAP/TPS) axis + if (offset < 272) { - fuelTable.values[15-offset/16][offset%16] = newValue; - return; + //X Axis + fuelTable.axisX[(offset - 256)] = ((int)(newValue) * 100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct } else { - //Check whether this is on the X (RPM) or Y (MAP/TPS) axis - if (offset < 272) - { - //X Axis - fuelTable.axisX[(offset-256)] = ((int)(newValue) * 100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct - } - else - { - //Y Axis - offset = 15-(offset-272); //Need to do a translation to flip the order (Due to us using (0,0) in the top left rather than bottom right - fuelTable.axisY[offset] = (int)(newValue); - } - return; + //Y Axis + offset = 15 - (offset - 272); //Need to do a translation to flip the order (Due to us using (0,0) in the top left rather than bottom right + fuelTable.axisY[offset] = (int)(newValue); } - break; - - case veSetPage: - pnt_configPage = &configPage1; //Setup a pointer to the relevant config page - //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size - if( offset < page_size) + return; + } + break; + + case veSetPage: + pnt_configPage = &configPage1; //Setup a pointer to the relevant config page + //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size + if ( offset < page_size) + { + *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages + } + break; + + case ignMapPage: //Ignition settings page (Page 2) + if (offset < 256) //New value is part of the ignition map + { + ignitionTable.values[15 - offset / 16][offset % 16] = newValue; + return; + } + else + { + //Check whether this is on the X (RPM) or Y (MAP/TPS) axis + if (offset < 272) { - *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages - } - break; - - case ignMapPage: //Ignition settings page (Page 2) - if (offset < 256) //New value is part of the ignition map - { - ignitionTable.values[15-offset/16][offset%16] = newValue; - return; + //X Axis + ignitionTable.axisX[(offset - 256)] = (int)(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct } else { - //Check whether this is on the X (RPM) or Y (MAP/TPS) axis - if (offset < 272) - { - //X Axis - ignitionTable.axisX[(offset-256)] = (int)(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiple it back by 100 to make it correct - } - else - { - //Y Axis - offset = 15-(offset-272); //Need to do a translation to flip the order - ignitionTable.axisY[offset] = (int)(newValue); - } - return; + //Y Axis + offset = 15 - (offset - 272); //Need to do a translation to flip the order + ignitionTable.axisY[offset] = (int)(newValue); } - - case ignSetPage: - pnt_configPage = &configPage2; - //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size - if( offset < page_size) + return; + } + + case ignSetPage: + pnt_configPage = &configPage2; + //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size + if ( offset < page_size) + { + *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages + } + break; + + case afrMapPage: //Air/Fuel ratio target settings page + if (offset < 256) //New value is part of the afr map + { + afrTable.values[15 - offset / 16][offset % 16] = newValue; + return; + } + else + { + //Check whether this is on the X (RPM) or Y (MAP/TPS) axis + if (offset < 272) { - *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages - } - break; - - case afrMapPage: //Air/Fuel ratio target settings page - if (offset < 256) //New value is part of the afr map - { - afrTable.values[15-offset/16][offset%16] = newValue; - return; + //X Axis + afrTable.axisX[(offset - 256)] = int(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiply it back by 100 to make it correct } else { - //Check whether this is on the X (RPM) or Y (MAP/TPS) axis - if (offset < 272) - { - //X Axis - afrTable.axisX[(offset-256)] = int(newValue) * int(100); //The RPM values sent by megasquirt are divided by 100, need to multiply it back by 100 to make it correct - } - else - { - //Y Axis - offset = 15-(offset-272); //Need to do a translation to flip the order - afrTable.axisY[offset] = int(newValue); - - } - return; + //Y Axis + offset = 15 - (offset - 272); //Need to do a translation to flip the order + afrTable.axisY[offset] = int(newValue); + } - - case afrSetPage: - pnt_configPage = &configPage3; - //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size - if( offset < page_size) - { - *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages - } - break; - - case iacPage: //Idle Air Control settings page (Page 4) - pnt_configPage = &configPage4; - //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size - if( offset < page_size) - { - *((byte *)pnt_configPage + (byte)offset) = newValue; - } - break; - case boostvvtPage: //Boost and VVT maps (8x8) - if (offset < 64) //New value is part of the boost map - { - boostTable.values[7-offset/8][offset%8] = newValue; - return; - } - else if (offset < 72) //New value is on the X (RPM) axis of the boost table - { - boostTable.axisX[(offset-64)] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct - return; - } - else if (offset < 80) //New value is on the Y (TPS) axis of the boost table - { - boostTable.axisY[(7-(offset-72))] = int(newValue); - return; - } - else if (offset < 144) //New value is part of the vvt map - { - offset = offset - 80; - vvtTable.values[7-offset/8][offset%8] = newValue; - return; - } - else if (offset < 152) //New value is on the X (RPM) axis of the vvt table - { - offset = offset - 144; - vvtTable.axisX[offset] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct - return; - } - else //New value is on the Y (Load) axis of the vvt table - { - offset = offset - 152; - vvtTable.axisY[(7-offset)] = int(newValue); - return; - } - default: - break; + return; + } + + case afrSetPage: + pnt_configPage = &configPage3; + //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size + if ( offset < page_size) + { + *((byte *)pnt_configPage + (byte)offset) = newValue; //Need to subtract 80 because the map and bins (Which make up 80 bytes) aren't part of the config pages + } + break; + + case iacPage: //Idle Air Control settings page (Page 4) + pnt_configPage = &configPage4; + //For some reason, TunerStudio is sending offsets greater than the maximum page size. I'm not sure if it's their bug or mine, but the fix is to only update the config page if the offset is less than the maximum size + if ( offset < page_size) + { + *((byte *)pnt_configPage + (byte)offset) = newValue; + } + break; + case boostvvtPage: //Boost and VVT maps (8x8) + if (offset < 64) //New value is part of the boost map + { + boostTable.values[7 - offset / 8][offset % 8] = newValue; + return; + } + else if (offset < 72) //New value is on the X (RPM) axis of the boost table + { + boostTable.axisX[(offset - 64)] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct + return; + } + else if (offset < 80) //New value is on the Y (TPS) axis of the boost table + { + boostTable.axisY[(7 - (offset - 72))] = int(newValue); + return; + } + else if (offset < 144) //New value is part of the vvt map + { + offset = offset - 80; + vvtTable.values[7 - offset / 8][offset % 8] = newValue; + return; + } + else if (offset < 152) //New value is on the X (RPM) axis of the vvt table + { + offset = offset - 144; + vvtTable.axisX[offset] = int(newValue) * int(100); //The RPM values sent by TunerStudio are divided by 100, need to multiply it back by 100 to make it correct + return; + } + else //New value is on the Y (Load) axis of the vvt table + { + offset = offset - 152; + vvtTable.axisY[(7 - offset)] = int(newValue); + return; + } + default: + break; } } /* -sendPage() packs the data within the current page (As set with the 'P' command) +sendPage() packs the data within the current page (As set with the 'P' command) into a buffer and sends it. Note that some translation of the data is required to lay it out in the way Megasqurit / TunerStudio expect it +useChar - If true, all values are send as chars, this is for the serial command line interface. TunerStudio expects data as raw values, so this must be set false in that case */ void sendPage(bool useChar) { void* pnt_configPage; struct table3D currentTable; - byte currentTitleIndex=0; - - switch (currentPage) + byte currentTitleIndex = 0; + + switch (currentPage) { - case veMapPage: + case veMapPage: { - currentTitleIndex = 0; - currentTable = fuelTable; - break; + currentTitleIndex = 0; + currentTable = fuelTable; + break; } - - case veSetPage: + + case veSetPage: { - // currentTitleIndex = 27; - if(useChar) - { - //To Display Values from Config Page 1 - Serial.println((const __FlashStringHelper *)&pageTitles[27]); - for(pnt_configPage=&configPage1;pnt_configPage<&configPage1.wueValues[0];pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - for(byte x=10;x;x--) + // currentTitleIndex = 27; + if (useChar) { - Serial.print(configPage1.wueValues[10-x]); - Serial.print(' '); + //To Display Values from Config Page 1 + Serial.println((const __FlashStringHelper *)&pageTitles[27]); + for (pnt_configPage = &configPage1; pnt_configPage < &configPage1.wueValues[0]; pnt_configPage = (byte *)pnt_configPage + 1) Serial.println(*((byte *)pnt_configPage)); + for (byte x = 10; x; x--) + { + Serial.print(configPage1.wueValues[10 - x]); + Serial.print(' '); + } + Serial.println(); + for (pnt_configPage = (byte *)&configPage1.wueValues[9] + 1; pnt_configPage < &configPage1.inj1Ang; pnt_configPage = (byte *)pnt_configPage + 1) { + Serial.println(*((byte *)pnt_configPage)); + } + for (pnt_configPage = &configPage1.inj1Ang; pnt_configPage < (unsigned int *)&configPage1.inj4Ang + 1; pnt_configPage = (unsigned int *)pnt_configPage + 1) Serial.println(*((unsigned int *)pnt_configPage)); + for (pnt_configPage = (unsigned int *)&configPage1.inj4Ang + 1; pnt_configPage < (byte *)&configPage1 + page_size; pnt_configPage = (byte *)pnt_configPage + 1) Serial.println(*((byte *)pnt_configPage)); + return; } - Serial.println(); - for(pnt_configPage=(byte *)&configPage1.wueValues[9]+1;pnt_configPage<&configPage1.inj1Ang;pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - for(pnt_configPage=&configPage1.inj1Ang;pnt_configPage<(unsigned int *)&configPage1.inj4Ang+1;pnt_configPage=(unsigned int *)pnt_configPage+1) Serial.println(*((unsigned int *)pnt_configPage)); - for(pnt_configPage=(unsigned int *)&configPage1.inj4Ang+1;pnt_configPage<(byte *)&configPage1+page_size;pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - return; - } - else pnt_configPage = &configPage1; //Create a pointer to Page 1 in memory - break; + else pnt_configPage = &configPage1; //Create a pointer to Page 1 in memory + break; } - - case ignMapPage: + + case ignMapPage: { - currentTitleIndex = 42; - currentTable = ignitionTable; - break; + currentTitleIndex = 42; + currentTable = ignitionTable; + break; } - - case ignSetPage: + + case ignSetPage: { - //currentTitleIndex = 56; - if(useChar) - { - //To Display Values from Config Page 2 - Serial.println((const __FlashStringHelper *)&pageTitles[56]); - Serial.println(configPage2.triggerAngle); - for(pnt_configPage=(int *)&configPage2+1;pnt_configPage<&configPage2.taeBins[0];pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - for(byte y=2;y;y--) + //currentTitleIndex = 56; + if (useChar) { - byte * currentVar; - if(y==2) currentVar=configPage2.taeBins; - else currentVar=configPage2.taeValues; - for(byte x=4;x;x--) - { - Serial.print(currentVar[4-x]); - Serial.print(' '); - } - Serial.println(); + //To Display Values from Config Page 2 + Serial.println((const __FlashStringHelper *)&pageTitles[56]); + Serial.println(configPage2.triggerAngle); + + for (pnt_configPage = (int *)&configPage2 + 1; pnt_configPage < &configPage2.taeBins[0]; pnt_configPage = (byte *)pnt_configPage + 1) Serial.println(*((byte *)pnt_configPage)); + for (byte y = 2; y; y--) + { + byte * currentVar; + if (y == 2) { + currentVar = configPage2.taeBins; + } + else { + currentVar = configPage2.taeValues; + } + + for (byte x = 4; x; x--) + { + Serial.print(currentVar[4 - x]); + Serial.print(' '); + } + Serial.println(); + } + for (byte x = 10; x ; x--) + { + Serial.print(configPage2.wueBins[10 - x]); + Serial.print(' '); + } + Serial.println(); + Serial.println(configPage2.dwellLimit); + for (byte x = 6; x; x--) + { + Serial.print(configPage2.dwellCorrectionValues[6 - x]); + Serial.print(' '); + } + Serial.println(); + for (pnt_configPage = (byte *)&configPage2.dwellCorrectionValues[5] + 1; pnt_configPage < (byte *)&configPage2 + page_size; pnt_configPage = (byte *)pnt_configPage + 1) + { + Serial.println(*((byte *)pnt_configPage)); + } + return; } - for(byte x=10;x;x--) - { - Serial.print(configPage2.wueBins[10-x]); - Serial.print(' '); - } - Serial.println(); - Serial.println(configPage2.dwellLimit); - for(byte x=6;x;x--) - { - Serial.print(configPage2.dwellCorrectionValues[6-x]); - Serial.print(' '); - } - Serial.println(); - for(pnt_configPage=(byte *)&configPage2.dwellCorrectionValues[5]+1;pnt_configPage<(byte *)&configPage2+page_size;pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - return; - } - else pnt_configPage = &configPage2; //Create a pointer to Page 2 in memory - break; + else pnt_configPage = &configPage2; //Create a pointer to Page 2 in memory + break; } - - case afrMapPage: + + case afrMapPage: { - currentTitleIndex = 71; - currentTable = afrTable; - break; + currentTitleIndex = 71; + currentTable = afrTable; + break; } - - case afrSetPage: + + case afrSetPage: { - //currentTitleIndex = 91; - if(useChar) - { - //To Display Values from Config Page 3 - Serial.println((const __FlashStringHelper *)&pageTitles[91]); - for(pnt_configPage=&configPage3;pnt_configPage<&configPage3.voltageCorrectionBins[0];pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - for(byte y=2;y;y--) + //currentTitleIndex = 91; + if (useChar) { - byte * currentVar; - if(y==2) currentVar=configPage3.voltageCorrectionBins; - else currentVar=configPage3.injVoltageCorrectionValues; - for(byte x=6;x;x--) - { - Serial.print(currentVar[6-x]); - Serial.print(' '); - } - Serial.println(); + //To Display Values from Config Page 3 + Serial.println((const __FlashStringHelper *)&pageTitles[91]); + for (pnt_configPage = &configPage3; pnt_configPage < &configPage3.voltageCorrectionBins[0]; pnt_configPage = (byte *)pnt_configPage + 1) + { + Serial.println(*((byte *)pnt_configPage)); + } + for (byte y = 2; y; y--) + { + byte * currentVar; + if (y == 2) { currentVar = configPage3.voltageCorrectionBins; } + else { currentVar = configPage3.injVoltageCorrectionValues; } + + for (byte x = 6; x; x--) + { + Serial.print(currentVar[6 - x]); + Serial.print(' '); + } + Serial.println(); + } + for (byte y = 2; y; y--) + { + byte* currentVar; + if (y == 2) currentVar = configPage3.airDenBins; + else currentVar = configPage3.airDenRates; + for (byte x = 9; x; x--) + { + Serial.print(currentVar[9 - x]); + Serial.print(' '); + } + Serial.println(); + } + for (pnt_configPage = (byte *)&configPage3.airDenRates[8] + 1; pnt_configPage < (byte *)&configPage3 + page_size; pnt_configPage = (byte *)pnt_configPage + 1) + { + Serial.println(*((byte *)pnt_configPage)); + } + return; } - for(byte y=2;y;y--) - { - byte* currentVar; - if(y==2) currentVar=configPage3.airDenBins; - else currentVar=configPage3.airDenRates; - for(byte x=9;x;x--) - { - Serial.print(currentVar[9-x]); - Serial.print(' '); - } - Serial.println(); - } - for(pnt_configPage=(byte *)&configPage3.airDenRates[8]+1;pnt_configPage<(byte *)&configPage3+page_size;pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - return; - } - else pnt_configPage = &configPage3; //Create a pointer to Page 3 in memory - break; + else pnt_configPage = &configPage3; //Create a pointer to Page 3 in memory + break; } - - case iacPage: + + case iacPage: { - //currentTitleIndex = 106; - //To Display Values from Config Page 4 - if(useChar) - { - Serial.println((const __FlashStringHelper *)&pageTitles[106]); - for(byte y=4;y;y--) + //currentTitleIndex = 106; + //To Display Values from Config Page 4 + if (useChar) { - byte * currentVar; - switch(y) - { - case 1: currentVar=configPage4.iacBins; break; - case 2: currentVar=configPage4.iacOLPWMVal; break; - case 3: currentVar=configPage4.iacOLStepVal; break; - case 4: currentVar=configPage4.iacCLValues; break; - default: break; - } - for(byte x=10;x;x--) - { - Serial.print(currentVar[10-x]); - Serial.print(' '); - } - Serial.println(); + Serial.println((const __FlashStringHelper *)&pageTitles[106]); + for (byte y = 4; y; y--) + { + byte * currentVar; + switch (y) + { + case 1: currentVar = configPage4.iacBins; break; + case 2: currentVar = configPage4.iacOLPWMVal; break; + case 3: currentVar = configPage4.iacOLStepVal; break; + case 4: currentVar = configPage4.iacCLValues; break; + default: break; + } + for (byte x = 10; x; x--) + { + Serial.print(currentVar[10 - x]); + Serial.print(' '); + } + Serial.println(); + } + for (byte y = 3; y; y--) + { + byte * currentVar; + switch (y) + { + case 1: currentVar = configPage4.iacCrankBins; break; + case 2: currentVar = configPage4.iacCrankDuty; break; + case 3: currentVar = configPage4.iacCrankSteps; break; + default: break; + } + for (byte x = 4; x; x--) + { + Serial.print(currentVar[4 - x]); + Serial.print(' '); + } + Serial.println(); + } + for (pnt_configPage = (byte *)&configPage4.iacCrankBins[3] + 1; pnt_configPage < (byte *)&configPage4 + page_size; pnt_configPage = (byte *)pnt_configPage + 1) Serial.println(*((byte *)pnt_configPage)); + return; } - for(byte y=3;y;y--) - { - byte * currentVar; - switch(y) - { - case 1: currentVar=configPage4.iacCrankBins; break; - case 2: currentVar=configPage4.iacCrankDuty; break; - case 3: currentVar=configPage4.iacCrankSteps; break; - default: break; - } - for(byte x=4;x;x--) - { - Serial.print(currentVar[4-x]); - Serial.print(' '); - } - Serial.println(); - } - for(pnt_configPage=(byte *)&configPage4.iacCrankBins[3]+1;pnt_configPage<(byte *)&configPage4+page_size;pnt_configPage=(byte *)pnt_configPage+1) Serial.println(*((byte *)pnt_configPage)); - return; - } - else pnt_configPage = &configPage4; //Create a pointer to Page 4 in memory - break; + else pnt_configPage = &configPage4; //Create a pointer to Page 4 in memory + break; } - case boostvvtPage: + + case boostvvtPage: { //Need to perform a translation of the values[MAP/TPS][RPM] into the MS expected format byte response[160]; //Bit hacky, but the size is: (8x8 + 8 + 8) + (8x8 + 8 + 8) = 160 - + //Boost table - for(int x=0;x<64;x++) { response[x] = boostTable.values[7-x/8][x%8]; } - for(int x=64;x<72;x++) { response[x] = byte(boostTable.axisX[(x-64)] / 100); } - for(int y=72;y<80;y++) { response[y] = byte(boostTable.axisY[7-(y-72)]); } + for (int x = 0; x < 64; x++) { response[x] = boostTable.values[7 - x / 8][x % 8]; } + for (int x = 64; x < 72; x++) { response[x] = byte(boostTable.axisX[(x - 64)] / 100); } + for (int y = 72; y < 80; y++) { response[y] = byte(boostTable.axisY[7 - (y - 72)]); } //VVT table - for(int x=0;x<64;x++) { response[x+80] = vvtTable.values[7-x/8][x%8]; } - for(int x=64;x<72;x++) { response[x+80] = byte(vvtTable.axisX[(x-64)] / 100); } - for(int y=72;y<80;y++) { response[y+80] = byte(vvtTable.axisY[7-(y-72)]); } + for (int x = 0; x < 64; x++) { response[x + 80] = vvtTable.values[7 - x / 8][x % 8]; } + for (int x = 64; x < 72; x++) { response[x + 80] = byte(vvtTable.axisX[(x - 64)] / 100); } + for (int y = 72; y < 80; y++) { response[y + 80] = byte(vvtTable.axisY[7 - (y - 72)]); } Serial.write((byte *)&response, sizeof(response)); return; break; - } - default: - { - Serial.println(F("\nPage has not been implemented yet. Change to another page.")); - return; - break; } - } - if(isMap) - { - if(useChar) - { - const char spaceChar = ' '; - /*while(pageTitles[currentTitleIndex]) - { - Serial.print(pageTitles[currentTitleIndex]); - currentTitleIndex++; - }*/ - Serial.println((const __FlashStringHelper *)&pageTitles[currentTitleIndex]); - Serial.print(F("\n ")); - for(int x=0;x 255) { tempValue = 255; } // Cap the maximum value to prevent overflow when converting to byte - if (tempValue < 0) { tempValue = 0; } - + if (tempValue > 255) { + tempValue = 255; // Cap the maximum value to prevent overflow when converting to byte + } + if (tempValue < 0) { + tempValue = 0; + } + pnt_TargetTable[(x / 2)] = (byte)tempValue; int y = EEPROM_CALIBRATION_O2 + counter; @@ -759,7 +789,9 @@ void receiveCalibration(byte tableID) analogWrite(13, (counter % 50) ); counter++; } - else { every2nd = true; } + else { + every2nd = true; + } } @@ -773,36 +805,38 @@ Send 256 tooth log entries void sendToothLog(bool useChar) { - //We need 256 records to send to TunerStudio. If there aren't that many in the buffer (Buffer is 512 long) then we just return and wait for the next call - if (toothHistoryIndex < 256) { return; } //Don't believe this is the best way to go. Just display whatever is in the buffer - unsigned int tempToothHistory[512]; //Create a temporary array that will contain a copy of what is in the main toothHistory array - - //Copy the working history into the temporary buffer array. This is done so that, if the history loops whilst the values are being sent over serial, it doesn't affect the values - memcpy( (void*)tempToothHistory, (void*)toothHistory, sizeof(tempToothHistory) ); - toothHistoryIndex = 0; //Reset the history index + //We need 256 records to send to TunerStudio. If there aren't that many in the buffer (Buffer is 512 long) then we just return and wait for the next call + if (toothHistoryIndex < 256) { + return; //Don't believe this is the best way to go. Just display whatever is in the buffer + } + unsigned int tempToothHistory[512]; //Create a temporary array that will contain a copy of what is in the main toothHistory array - //Loop only needs to go to 256 (Even though the buffer is 512 long) as we only ever send 256 entries at a time - if (useChar) - { - for(int x=0; x<256; x++) - { - Serial.println(tempToothHistory[x]); - } - } - else - { - for(int x=0; x<256; x++) - { - Serial.write(highByte(tempToothHistory[x])); - Serial.write(lowByte(tempToothHistory[x])); - } - } - Serial.flush(); + //Copy the working history into the temporary buffer array. This is done so that, if the history loops whilst the values are being sent over serial, it doesn't affect the values + memcpy( (void*)tempToothHistory, (void*)toothHistory, sizeof(tempToothHistory) ); + toothHistoryIndex = 0; //Reset the history index + + //Loop only needs to go to 256 (Even though the buffer is 512 long) as we only ever send 256 entries at a time + if (useChar) + { + for (int x = 0; x < 256; x++) + { + Serial.println(tempToothHistory[x]); + } + } + else + { + for (int x = 0; x < 256; x++) + { + Serial.write(highByte(tempToothHistory[x])); + Serial.write(lowByte(tempToothHistory[x])); + } + } + Serial.flush(); } - + void testComm() { Serial.write(1); - return; + return; } From 8a0615d9beda19e60beac7a9b7e8d3b98aaf6086 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Tue, 13 Oct 2015 09:56:46 +1100 Subject: [PATCH 4/4] Remove serial flush --- comms.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/comms.ino b/comms.ino index 74ef766..ad25086 100644 --- a/comms.ino +++ b/comms.ino @@ -831,7 +831,7 @@ void sendToothLog(bool useChar) Serial.write(lowByte(tempToothHistory[x])); } } - Serial.flush(); + //Serial.flush(); }