/* Speeduino - Simple engine management for the Arduino Mega 2560 platform Copyright (C) Josh Stewart A full copy of the license may be found in the projects root directory can_comms was originally contributed by Darren Siepka */ /* can_command is called when a command is received over serial3 from the Can interface It parses the command and calls the relevant function sendcancommand is called when a comman d is to be sent via serial3 to the Can interface */ #include "globals.h" #include "cancomms.h" #include "maths.h" #include "errors.h" #include "utils.h" void canCommand() { currentcanCommand = CANSerial.read(); switch (currentcanCommand) { case 'A': // sends the bytes of realtime values from the CAN list sendcanValues(0, CAN_PACKET_SIZE, 0x30, 1); //send values to serial3 break; case 'G': // this is the reply command sent by the Can interface byte destcaninchannel; if (CANSerial.available() >= 9) { cancmdfail = CANSerial.read(); //0 == fail, 1 == good. destcaninchannel = CANSerial.read(); // the input channel that requested the data value if (cancmdfail != 0) { // read all 8 bytes of data. for (byte Gx = 0; Gx < 8; Gx++) // first two are the can address the data is from. next two are the can address the data is for.then next 1 or two bytes of data { Gdata[Gx] = CANSerial.read(); } Glow = Gdata[(configPage9.caninput_source_start_byte[destcaninchannel]&7)]; if ((BIT_CHECK(configPage9.caninput_source_num_bytes,destcaninchannel))) //if true then num bytes is 2 { if ((configPage9.caninput_source_start_byte[destcaninchannel]&7) < 8) //you cant have a 2 byte value starting at byte 7(8 on the list) { Ghigh = Gdata[((configPage9.caninput_source_start_byte[destcaninchannel]&7)+1)]; } else{Ghigh = 0;} } else { Ghigh = 0; } currentStatus.canin[destcaninchannel] = (Ghigh<<8) | Glow; } else{} //continue as command request failed and/or data/device was not available } break; case 'L': uint8_t Llength; while (CANSerial.available() == 0) { } canlisten = CANSerial.read(); if (canlisten == 0) { //command request failed and/or data/device was not available break; } while (CANSerial.available() == 0) { } Llength= CANSerial.read(); // next the number of bytes expected value for (uint8_t Lcount = 0; Lcount = 6) { CANSerial.read(); //Read the $tsCanId Cmd = CANSerial.read(); uint16_t offset, length; if( (Cmd == 0x30) || ( (Cmd >= 0x40) && (Cmd <0x50) ) ) //Send output channels command 0x30 is 48dec, 0x40(64dec)-0x4F(79dec) are external can request { byte tmp; tmp = CANSerial.read(); offset = word(CANSerial.read(), tmp); tmp = CANSerial.read(); length = word(CANSerial.read(), tmp); sendcanValues(offset, length,Cmd, 1); //Serial.print(Cmd); } else { //No other r/ commands should be called } } break; case 's': // send the "a" stream code version CANSerial.write("Speeduino csx02018.7"); break; case 'S': // send code version CANSerial.write("Speeduino 2018.7-dev"); break; case 'Q': // send code version for (unsigned int revn = 0; revn < sizeof( TSfirmwareVersion) - 1; revn++) { CANSerial.write( TSfirmwareVersion[revn]); } //Serial3.print("speeduino 201609-dev"); break; case 'Z': //dev use break; default: break; } } void sendcanValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portType) { byte fullStatus[CAN_PACKET_SIZE]; //CAN serial #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)|| defined(CORE_STM32) || defined (CORE_TEENSY) //ATmega2561 does not have Serial3 if (offset == 0) { CANSerial.write("A"); //confirm cmd type } else { CANSerial.write("r"); //confirm cmd type CANSerial.write(cmd); } #endif currentStatus.spark ^= (-currentStatus.hasSync ^ currentStatus.spark) & (1 << BIT_SPARK_SYNC); //Set the sync bit of the Spark variable to match the hasSync variable 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.status1; //status1 Bitfield fullStatus[2] = currentStatus.engine; //Engine Status Bitfield fullStatus[3] = (byte)(divu100(currentStatus.dwell)); //Dwell in ms * 10 fullStatus[4] = lowByte(currentStatus.MAP); //2 bytes for MAP fullStatus[5] = highByte(currentStatus.MAP); fullStatus[6] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); //mat fullStatus[7] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //Coolant ADC fullStatus[8] = currentStatus.batCorrection; //Battery voltage correction (%) fullStatus[9] = currentStatus.battery10; //battery voltage fullStatus[10] = currentStatus.O2; //O2 fullStatus[11] = currentStatus.egoCorrection; //Exhaust gas correction (%) fullStatus[12] = currentStatus.iatCorrection; //Air temperature Correction (%) fullStatus[13] = currentStatus.wueCorrection; //Warmup enrichment (%) fullStatus[14] = lowByte(currentStatus.RPM); //rpm HB fullStatus[15] = highByte(currentStatus.RPM); //rpm LB fullStatus[16] = currentStatus.TAEamount; //acceleration enrichment (%) fullStatus[17] = currentStatus.corrections; //Total GammaE (%) fullStatus[18] = currentStatus.VE; //Current VE 1 (%) fullStatus[19] = currentStatus.afrTarget; fullStatus[20] = lowByte(currentStatus.PW1); //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS. fullStatus[21] = highByte(currentStatus.PW1); //Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS. fullStatus[22] = currentStatus.tpsDOT; //TPS DOT fullStatus[23] = currentStatus.advance; fullStatus[24] = currentStatus.TPS; // TPS (0% to 100%) //Need to split the int loopsPerSecond value into 2 bytes fullStatus[25] = lowByte(currentStatus.loopsPerSecond); fullStatus[26] = highByte(currentStatus.loopsPerSecond); //The following can be used to show the amount of free memory currentStatus.freeRAM = freeRam(); fullStatus[27] = lowByte(currentStatus.freeRAM); //(byte)((currentStatus.loopsPerSecond >> 8) & 0xFF); fullStatus[28] = highByte(currentStatus.freeRAM); fullStatus[29] = (byte)(currentStatus.boostTarget >> 1); //Divide boost target by 2 to fit in a byte fullStatus[30] = (byte)(currentStatus.boostDuty / 100); fullStatus[31] = currentStatus.spark; //Spark related bitfield //rpmDOT must be sent as a signed integer fullStatus[32] = lowByte(currentStatus.rpmDOT); fullStatus[33] = highByte(currentStatus.rpmDOT); fullStatus[34] = currentStatus.ethanolPct; //Flex sensor value (or 0 if not used) fullStatus[35] = currentStatus.flexCorrection; //Flex fuel correction (% above or below 100) fullStatus[36] = currentStatus.flexIgnCorrection; //Ignition correction (Increased degrees of advance) for flex fuel fullStatus[37] = currentStatus.idleLoad; fullStatus[38] = currentStatus.testOutputs; fullStatus[39] = currentStatus.O2_2; //O2 fullStatus[40] = currentStatus.baro; //Barometer value fullStatus[41] = lowByte(currentStatus.canin[0]); fullStatus[42] = highByte(currentStatus.canin[0]); fullStatus[43] = lowByte(currentStatus.canin[1]); fullStatus[44] = highByte(currentStatus.canin[1]); fullStatus[45] = lowByte(currentStatus.canin[2]); fullStatus[46] = highByte(currentStatus.canin[2]); fullStatus[47] = lowByte(currentStatus.canin[3]); fullStatus[48] = highByte(currentStatus.canin[3]); fullStatus[49] = lowByte(currentStatus.canin[4]); fullStatus[50] = highByte(currentStatus.canin[4]); fullStatus[51] = lowByte(currentStatus.canin[5]); fullStatus[52] = highByte(currentStatus.canin[5]); fullStatus[53] = lowByte(currentStatus.canin[6]); fullStatus[54] = highByte(currentStatus.canin[6]); fullStatus[55] = lowByte(currentStatus.canin[7]); fullStatus[56] = highByte(currentStatus.canin[7]); fullStatus[57] = lowByte(currentStatus.canin[8]); fullStatus[58] = highByte(currentStatus.canin[8]); fullStatus[59] = lowByte(currentStatus.canin[9]); fullStatus[60] = highByte(currentStatus.canin[9]); fullStatus[61] = lowByte(currentStatus.canin[10]); fullStatus[62] = highByte(currentStatus.canin[10]); fullStatus[63] = lowByte(currentStatus.canin[11]); fullStatus[64] = highByte(currentStatus.canin[11]); fullStatus[65] = lowByte(currentStatus.canin[12]); fullStatus[66] = highByte(currentStatus.canin[12]); fullStatus[67] = lowByte(currentStatus.canin[13]); fullStatus[68] = highByte(currentStatus.canin[13]); fullStatus[69] = lowByte(currentStatus.canin[14]); fullStatus[70] = highByte(currentStatus.canin[14]); fullStatus[71] = lowByte(currentStatus.canin[15]); fullStatus[72] = highByte(currentStatus.canin[15]); fullStatus[73] = currentStatus.tpsADC; fullStatus[74] = getNextError(); for(byte x=0; x