/* This is called when a command is received over serial from TunerStudio / Megatune It parses the command and calls the relevant function A detailed description of each call can be found at: http://www.msextra.com/doc/ms1extra/COM_RS232.htm */ void command() { switch (Serial.read()) { case 'A': // send 22 bytes of realtime values sendValues(22); 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 'P': // set the current page //Blue digitalWrite(10, HIGH); digitalWrite(9, LOW); digitalWrite(13, LOW); //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(); break; case 'R': // send 39 bytes of realtime values sendValues(39); break; case 'S': // send code version Serial.write(ms_version); break; case 'Q': // send code version //Off digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(13, LOW); Serial.write(ms_version); break; case 'V': // send VE table and constants //Red digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(13, HIGH); sendPage(); break; case 'W': // receive new VE or constant at 'W'++ //Green digitalWrite(9, HIGH); digitalWrite(10, LOW); digitalWrite(13, LOW); receiveValue(Serial.read(), Serial.read()); break; default: break; } } /* This function returns the current values of a fixed group of variables */ void sendValues(int length) { byte response[22]; response[0] = (uint8_t)1; //rtc.sec; boolean a = 0; //inj_port1.status; boolean b = 0; //inj_port2.status; response[1] = ((a & 0x01) << 0) | ((a & 0x02) << 1) | ((a & 0x04) << 1) | ((b & 0x01) << 1) | ((b & 0x02) << 3) | ((b & 0x04) << 3); //squirt NOT YET WORKING response[2] = (byte)128; // Engine Status NOT YET WORKING response[3] = 0x00; //baro response[4] = currentStatus.MAP; //map response[5] = 0x00; //mat response[6] = 0x00; //Coolant response[7] = 0x00; //TPS response[8] = 0x00; //battery voltage response[9] = 0x00; //O2 response[10] = 0x00; //Exhaust gas correction (%) response[11] = 0x00; //Air Correction (%) response[12] = 0x00; //Warmup enrichment (%) response[13] = (currentStatus.RPM / 100); //rpm / 100 response[14] = currentStatus.PW / 100; //Pulsewidth 1 divided by 10 (in ms) response[15] = 0x00; //acceleration enrichment (ms) response[16] = 0x00; //Barometer correction (%) response[17] = 0x00; //Total GammaE (%) response[18] = currentStatus.VE; //Current VE 1 (%) response[19] = 0x00; //Pulsewidth 2 divided by 10 (in ms) response[20] = 0x00; //mCurrent VE 2 (%) response[21] = 0x00; //Idle Serial.write(response, (size_t)22); return; } void receiveValue(byte offset, byte newValue) { byte* pnt_configPage; switch (currentPage) { case vePage: pnt_configPage = (byte *)&configPage1; if (offset < 64) //New value is part of the fuel map { } else if (offset < 80) //New value is one of the X or Y axis bins { } else //New value is one of the remaining config items { *(pnt_configPage + offset) = newValue; } break; case ignPage: //Ignition settings page (Page 2) pnt_configPage = (byte *)&configPage2; if (offset < 64) //New value is part of the ignition map { } else if (offset < 80) //New value is one of the X or Y axis bins { } else //New value is one of the remaining config items { *(pnt_configPage + offset) = newValue; } break; default: break; } } void sendPage() { byte response[page_size]; byte offset; byte* pnt_configPage; switch ((int)currentPage) { case vePage: //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 for(byte x=0;x<64;x++) { response[x] = fuelTable.values[7-x/8][x%8]; } for(byte x=64;x<72;x++) { response[x] = fuelTable.axisX[(x-64)] / 100; } //RPM Bins for VE table (Need to be dvidied by 100) for(byte y=72;y<80;y++) { response[y] = fuelTable.axisY[7-(y-72)]; } //MAP or TPS bins for VE table //All other bytes can simply be copied from the config table pnt_configPage = (byte *)&configPage1; //Create a pointer to Page 1 in memory offset = 80; //Offset is based on the amount already copied above (table + bins) for(byte x=offset; x