diff --git a/libraries/AP_PiccoloCAN/AP_PiccoloCAN.cpp b/libraries/AP_PiccoloCAN/AP_PiccoloCAN.cpp index 92645ac8f1..75be8aafff 100644 --- a/libraries/AP_PiccoloCAN/AP_PiccoloCAN.cpp +++ b/libraries/AP_PiccoloCAN/AP_PiccoloCAN.cpp @@ -1059,4 +1059,71 @@ uint32_t getServoPacketID(const void* pkt) return (uint32_t) ((frame->id >> 16) & 0xFF); } +/* Piccolo Glue Logic + * The following functions are required by the auto-generated protogen code. + */ + + +//! \return the packet data pointer from the packet +uint8_t* getECUPacketData(void* pkt) +{ + AP_HAL::CANFrame* frame = (AP_HAL::CANFrame*) pkt; + + return (uint8_t*) frame->data; +} + +//! \return the packet data pointer from the packet, const +const uint8_t* getECUPacketDataConst(const void* pkt) +{ + AP_HAL::CANFrame* frame = (AP_HAL::CANFrame*) pkt; + + return (const uint8_t*) frame->data; +} + +//! Complete a packet after the data have been encoded +void finishECUPacket(void* pkt, int size, uint32_t packetID) +{ + AP_HAL::CANFrame* frame = (AP_HAL::CANFrame*) pkt; + + if (size > AP_HAL::CANFrame::MaxDataLen) { + size = AP_HAL::CANFrame::MaxDataLen; + } + + frame->dlc = size; + + /* Encode the CAN ID + * 0x09mmdddd + * - 07 = ECU_IN (to and ECU) group ID + * - mm = Message ID + * - dd = Device ID + * + * Note: The Device ID (lower 16 bits of the frame ID) will have to be inserted later + */ + + uint32_t id = (((uint8_t) AP_PiccoloCAN::MessageGroup::ECU_IN) << 24) | // CAN Group ID + ((packetID & 0xFF) << 16); // Message ID + + // Extended frame format + id |= AP_HAL::CANFrame::FlagEFF; + + frame->id = id; +} + +//! \return the size of a packet from the packet header +int getECUPacketSize(const void* pkt) +{ + AP_HAL::CANFrame* frame = (AP_HAL::CANFrame*) pkt; + + return (int) frame->dlc; +} + +//! \return the ID of a packet from the packet header +uint32_t getECUPacketID(const void* pkt) +{ + AP_HAL::CANFrame* frame = (AP_HAL::CANFrame*) pkt; + + // Extract the message ID field from the 29-bit ID + return (uint32_t) ((frame->id >> 16) & 0xFF); +} + #endif // HAL_PICCOLO_CAN_ENABLE diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUDefines.c b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUDefines.c new file mode 100644 index 0000000000..1af342789b --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUDefines.c @@ -0,0 +1,663 @@ +// ECUDefines.c was generated by ProtoGen version 3.2.a + +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Author: Oliver Walters / Currawong Engineering Pty Ltd + */ + + +#include "ECUDefines.h" +#include "fielddecode.h" +#include "fieldencode.h" +#include "scaleddecode.h" +#include "scaledencode.h" + +/*! + * \brief Encode a ECU_AuxiliaryErrorBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_AuxiliaryErrorBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_AuxiliaryErrorBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // 1 if CAN servo is not connected + _pg_data[_pg_byteindex] = (uint8_t)((_pg_user->servoLink == true) ? 1 : 0) << 7; + + // 1 if CAN servo is reporting a position error + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->servoPosition == true) ? 1 : 0) << 6; + + // Reserved for future use + // Range of reserved_A is 0 to 63. + _pg_data[_pg_byteindex] |= (uint8_t)_pg_user->reserved_A; + + // Reserved for future use + // Range of reserved_B is 0 to 255. + _pg_data[_pg_byteindex + 1] = (uint8_t)_pg_user->reserved_B; + + // Reserved for future use + // Range of reserved_C is 0 to 255. + _pg_data[_pg_byteindex + 2] = (uint8_t)_pg_user->reserved_C; + + // Reserved for future use + // Range of reserved_D is 0 to 255. + _pg_data[_pg_byteindex + 3] = (uint8_t)_pg_user->reserved_D; + _pg_byteindex += 4; // close bit field + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_AuxiliaryErrorBits_t + +/*! + * \brief Decode a ECU_AuxiliaryErrorBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_AuxiliaryErrorBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_AuxiliaryErrorBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // 1 if CAN servo is not connected + _pg_user->servoLink = ((_pg_data[_pg_byteindex] >> 7)) ? true : false; + + // 1 if CAN servo is reporting a position error + _pg_user->servoPosition = (((_pg_data[_pg_byteindex] >> 6) & 0x1)) ? true : false; + + // Reserved for future use + // Range of reserved_A is 0 to 63. + _pg_user->reserved_A = ((_pg_data[_pg_byteindex]) & 0x3F); + + // Reserved for future use + // Range of reserved_B is 0 to 255. + _pg_user->reserved_B = _pg_data[_pg_byteindex + 1]; + + // Reserved for future use + // Range of reserved_C is 0 to 255. + _pg_user->reserved_C = _pg_data[_pg_byteindex + 2]; + + // Reserved for future use + // Range of reserved_D is 0 to 255. + _pg_user->reserved_D = _pg_data[_pg_byteindex + 3]; + _pg_byteindex += 4; // close bit field + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_AuxiliaryErrorBits_t + +/*! + * \brief Encode a ECU_AutronicErrorBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_AutronicErrorBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_AutronicErrorBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Reserved + _pg_data[_pg_byteindex] = 0; + + // Knock control error + _pg_data[_pg_byteindex + 1] = (uint8_t)_pg_user->knockControl << 7; + + // AF closed loop error + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_user->afCloseLoop << 6; + + // EEPROM error + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_user->eepromError << 5; + + // CMOS RAM error + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_user->cmosRam << 4; + + // Over voltage error + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_user->overVoltage << 3; + + // Power down error + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_user->powerDown << 2; + + // Knock sensor error + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_user->knockSensor << 1; + + // Over boost error + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_user->overBoost; + + // CAM2 position error + _pg_data[_pg_byteindex + 2] = (uint8_t)_pg_user->cam2Pos << 7; + + // CAM1 position error + _pg_data[_pg_byteindex + 2] |= (uint8_t)_pg_user->cam1Pos << 6; + + // High speed input 1 error + _pg_data[_pg_byteindex + 2] |= (uint8_t)_pg_user->highSpeedInput2 << 5; + + // High speed input 2 error + _pg_data[_pg_byteindex + 2] |= (uint8_t)_pg_user->highSpeedInput1 << 4; + + // Set if too many cylinder pulses + _pg_data[_pg_byteindex + 2] |= (uint8_t)_pg_user->tooManyCylPulse << 3; + + // Set if too few cylinder pulses + _pg_data[_pg_byteindex + 2] |= (uint8_t)_pg_user->tooFewCylPulse << 2; + + // Set if sync input pulse missing + _pg_data[_pg_byteindex + 2] |= (uint8_t)_pg_user->syncInputPulseMissing << 1; + + // Set if cylinder input pulse missing + _pg_data[_pg_byteindex + 2] |= (uint8_t)_pg_user->cylinderInputPulseMissing; + + // Air fuel sensor 2 error + _pg_data[_pg_byteindex + 3] = (uint8_t)_pg_user->af2Sensor << 7; + + // Air fuel sensor 1 error + _pg_data[_pg_byteindex + 3] |= (uint8_t)_pg_user->af1Sensor << 6; + + // Barometric pressure sensor error + _pg_data[_pg_byteindex + 3] |= (uint8_t)_pg_user->baroSensor << 5; + + // Exhaust back pressure sensor error + _pg_data[_pg_byteindex + 3] |= (uint8_t)_pg_user->ebpSensor << 4; + + // Manifold pressure sensor error + _pg_data[_pg_byteindex + 3] |= (uint8_t)_pg_user->mapSensor << 3; + + // Throttle position sensor error + _pg_data[_pg_byteindex + 3] |= (uint8_t)_pg_user->tpsSensor << 2; + + // Cylinder head temperature sensor error + _pg_data[_pg_byteindex + 3] |= (uint8_t)_pg_user->chtSensor << 1; + + // Manifold pressure sensor error + _pg_data[_pg_byteindex + 3] |= (uint8_t)_pg_user->matSensor; + _pg_byteindex += 4; // close bit field + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_AutronicErrorBits_t + +/*! + * \brief Decode a ECU_AutronicErrorBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_AutronicErrorBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_AutronicErrorBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Reserved + + // Knock control error + _pg_user->knockControl = (_pg_data[_pg_byteindex + 1] >> 7); + + // AF closed loop error + _pg_user->afCloseLoop = ((_pg_data[_pg_byteindex + 1] >> 6) & 0x1); + + // EEPROM error + _pg_user->eepromError = ((_pg_data[_pg_byteindex + 1] >> 5) & 0x1); + + // CMOS RAM error + _pg_user->cmosRam = ((_pg_data[_pg_byteindex + 1] >> 4) & 0x1); + + // Over voltage error + _pg_user->overVoltage = ((_pg_data[_pg_byteindex + 1] >> 3) & 0x1); + + // Power down error + _pg_user->powerDown = ((_pg_data[_pg_byteindex + 1] >> 2) & 0x1); + + // Knock sensor error + _pg_user->knockSensor = ((_pg_data[_pg_byteindex + 1] >> 1) & 0x1); + + // Over boost error + _pg_user->overBoost = ((_pg_data[_pg_byteindex + 1]) & 0x1); + + // CAM2 position error + _pg_user->cam2Pos = (_pg_data[_pg_byteindex + 2] >> 7); + + // CAM1 position error + _pg_user->cam1Pos = ((_pg_data[_pg_byteindex + 2] >> 6) & 0x1); + + // High speed input 1 error + _pg_user->highSpeedInput2 = ((_pg_data[_pg_byteindex + 2] >> 5) & 0x1); + + // High speed input 2 error + _pg_user->highSpeedInput1 = ((_pg_data[_pg_byteindex + 2] >> 4) & 0x1); + + // Set if too many cylinder pulses + _pg_user->tooManyCylPulse = ((_pg_data[_pg_byteindex + 2] >> 3) & 0x1); + + // Set if too few cylinder pulses + _pg_user->tooFewCylPulse = ((_pg_data[_pg_byteindex + 2] >> 2) & 0x1); + + // Set if sync input pulse missing + _pg_user->syncInputPulseMissing = ((_pg_data[_pg_byteindex + 2] >> 1) & 0x1); + + // Set if cylinder input pulse missing + _pg_user->cylinderInputPulseMissing = ((_pg_data[_pg_byteindex + 2]) & 0x1); + + // Air fuel sensor 2 error + _pg_user->af2Sensor = (_pg_data[_pg_byteindex + 3] >> 7); + + // Air fuel sensor 1 error + _pg_user->af1Sensor = ((_pg_data[_pg_byteindex + 3] >> 6) & 0x1); + + // Barometric pressure sensor error + _pg_user->baroSensor = ((_pg_data[_pg_byteindex + 3] >> 5) & 0x1); + + // Exhaust back pressure sensor error + _pg_user->ebpSensor = ((_pg_data[_pg_byteindex + 3] >> 4) & 0x1); + + // Manifold pressure sensor error + _pg_user->mapSensor = ((_pg_data[_pg_byteindex + 3] >> 3) & 0x1); + + // Throttle position sensor error + _pg_user->tpsSensor = ((_pg_data[_pg_byteindex + 3] >> 2) & 0x1); + + // Cylinder head temperature sensor error + _pg_user->chtSensor = ((_pg_data[_pg_byteindex + 3] >> 1) & 0x1); + + // Manifold pressure sensor error + _pg_user->matSensor = ((_pg_data[_pg_byteindex + 3]) & 0x1); + _pg_byteindex += 4; // close bit field + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_AutronicErrorBits_t + +/*! + * \brief Encode a ECU_ErrorBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_ErrorBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_ErrorBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Error information for autronic processor + encodeECU_AutronicErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->autronic); + + // Error information for auxiliary processor + encodeECU_AuxiliaryErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->auxiliary); + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_ErrorBits_t + +/*! + * \brief Decode a ECU_ErrorBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_ErrorBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_ErrorBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Error information for autronic processor + if(decodeECU_AutronicErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->autronic) == 0) + return 0; + + // Error information for auxiliary processor + if(decodeECU_AuxiliaryErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->auxiliary) == 0) + return 0; + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_ErrorBits_t + +/*! + * \brief Encode a ECU_ThrottleDelayConfigBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_ThrottleDelayConfigBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_ThrottleDelayConfigBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // reserved for future use + // Range of reserved is 0 to 127. + _pg_data[_pg_byteindex] = (uint8_t)_pg_user->reserved << 1; + + // Set to base the delay on temperature, else the delay is manually set + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->delayOnTemp == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_ThrottleDelayConfigBits_t + +/*! + * \brief Decode a ECU_ThrottleDelayConfigBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_ThrottleDelayConfigBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_ThrottleDelayConfigBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // reserved for future use + // Range of reserved is 0 to 127. + _pg_user->reserved = (_pg_data[_pg_byteindex] >> 1); + + // Set to base the delay on temperature, else the delay is manually set + _pg_user->delayOnTemp = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_ThrottleDelayConfigBits_t + +/*! + * \brief Encode a ECU_ThrottleConfigBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_ThrottleConfigBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_ThrottleConfigBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Enable pass-through of CAN servo data over serial link + _pg_data[_pg_byteindex] = (uint8_t)((_pg_user->servoPassthrough == true) ? 1 : 0) << 7; + + // Reserved for future use + + // Set if the CAN throttle is detected + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->canThrottleDetected == true) ? 1 : 0) << 1; + + // Set if CAN throttle is enabled. This bit is ignored when this packet is sent to the ECU. To enable CAN throttle you must use system commands + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->canThrottle == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_ThrottleConfigBits_t + +/*! + * \brief Decode a ECU_ThrottleConfigBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_ThrottleConfigBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_ThrottleConfigBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Enable pass-through of CAN servo data over serial link + _pg_user->servoPassthrough = ((_pg_data[_pg_byteindex] >> 7)) ? true : false; + + // Reserved for future use + + // Set if the CAN throttle is detected + _pg_user->canThrottleDetected = (((_pg_data[_pg_byteindex] >> 1) & 0x1)) ? true : false; + + // Set if CAN throttle is enabled. This bit is ignored when this packet is sent to the ECU. To enable CAN throttle you must use system commands + _pg_user->canThrottle = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_ThrottleConfigBits_t + +/*! + * \brief Encode a ECU_ThrottleCurveConfigBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_ThrottleCurveConfigBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_ThrottleCurveConfigBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Reserved for future use + _pg_data[_pg_byteindex] = 0; + + // Throttle curve is active + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->curveActive == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_ThrottleCurveConfigBits_t + +/*! + * \brief Decode a ECU_ThrottleCurveConfigBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_ThrottleCurveConfigBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_ThrottleCurveConfigBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Reserved for future use + + // Throttle curve is active + _pg_user->curveActive = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_ThrottleCurveConfigBits_t + +/*! + * \brief Encode a ECU_ECUSettings_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_ECUSettings_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_ECUSettings_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Range of powerCycles is 0 to 65535. + uint16ToBeBytes(_pg_user->powerCycles, _pg_data, &_pg_byteindex); + + // Deprecated - DO NOT USE + // Range of customerID_deprecated is 0 to 65535. + uint16ToBeBytes(_pg_user->customerID_deprecated, _pg_data, &_pg_byteindex); + + // Range of versionHardware is 0 to 255. + uint8ToBytes(_pg_user->versionHardware, _pg_data, &_pg_byteindex); + + // reserved for future use + // Range of reservedA is 0 to 255. + uint8ToBytes(_pg_user->reservedA, _pg_data, &_pg_byteindex); + + // reserved for future use + // Range of reservedB is 0 to 255. + uint8ToBytes(_pg_user->reservedB, _pg_data, &_pg_byteindex); + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_ECUSettings_t + +/*! + * \brief Decode a ECU_ECUSettings_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_ECUSettings_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_ECUSettings_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Range of powerCycles is 0 to 65535. + _pg_user->powerCycles = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Deprecated - DO NOT USE + // Range of customerID_deprecated is 0 to 65535. + _pg_user->customerID_deprecated = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of versionHardware is 0 to 255. + _pg_user->versionHardware = uint8FromBytes(_pg_data, &_pg_byteindex); + + // reserved for future use + // Range of reservedA is 0 to 255. + _pg_user->reservedA = uint8FromBytes(_pg_data, &_pg_byteindex); + + // reserved for future use + // Range of reservedB is 0 to 255. + _pg_user->reservedB = uint8FromBytes(_pg_data, &_pg_byteindex); + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_ECUSettings_t + +/*! + * \brief Encode a ECU_CompileOptions_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_CompileOptions_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_CompileOptions_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // If set, the ECU will pass servo CAN packet data over the serial link + _pg_data[_pg_byteindex] = (uint8_t)((_pg_user->servoPassthrough == true) ? 1 : 0) << 7; + + // If set, the ECU will decode CAN messages in the PICCOLO_DATA_UP group + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->piccoloUplink == true) ? 1 : 0) << 6; + + // If set, the ECU supports Autronic message passthrough + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->autronicRelay == true) ? 1 : 0) << 5; + + // If set, the ECU supports redundant fuel pump control + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->dualPump == true) ? 1 : 0) << 4; + + // If set, the ECU runs a PI controller for fuel pressure. If not set, it uses bang-bang control + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->piPump == true) ? 1 : 0) << 3; + + // If set, the ECU will automatically compensate for degredation of the MAP sensor over time + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->mapCorrection == true) ? 1 : 0) << 2; + + // If set, the ECU watchdog timer is enabled + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->watchdog == true) ? 1 : 0) << 1; + + // If set, the ECU is compiled with extra debug functionality enabled + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->debug == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + // Reserved for future use + uint8ToBytes((uint8_t)(0), _pg_data, &_pg_byteindex); + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_CompileOptions_t + +/*! + * \brief Decode a ECU_CompileOptions_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_CompileOptions_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_CompileOptions_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // If set, the ECU will pass servo CAN packet data over the serial link + _pg_user->servoPassthrough = ((_pg_data[_pg_byteindex] >> 7)) ? true : false; + + // If set, the ECU will decode CAN messages in the PICCOLO_DATA_UP group + _pg_user->piccoloUplink = (((_pg_data[_pg_byteindex] >> 6) & 0x1)) ? true : false; + + // If set, the ECU supports Autronic message passthrough + _pg_user->autronicRelay = (((_pg_data[_pg_byteindex] >> 5) & 0x1)) ? true : false; + + // If set, the ECU supports redundant fuel pump control + _pg_user->dualPump = (((_pg_data[_pg_byteindex] >> 4) & 0x1)) ? true : false; + + // If set, the ECU runs a PI controller for fuel pressure. If not set, it uses bang-bang control + _pg_user->piPump = (((_pg_data[_pg_byteindex] >> 3) & 0x1)) ? true : false; + + // If set, the ECU will automatically compensate for degredation of the MAP sensor over time + _pg_user->mapCorrection = (((_pg_data[_pg_byteindex] >> 2) & 0x1)) ? true : false; + + // If set, the ECU watchdog timer is enabled + _pg_user->watchdog = (((_pg_data[_pg_byteindex] >> 1) & 0x1)) ? true : false; + + // If set, the ECU is compiled with extra debug functionality enabled + _pg_user->debug = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + // Reserved for future use + _pg_byteindex += 1; + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_CompileOptions_t + +// end of ECUDefines.c diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUDefines.h b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUDefines.h new file mode 100644 index 0000000000..f8d59f1b4e --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUDefines.h @@ -0,0 +1,218 @@ +// ECUDefines.h was generated by ProtoGen version 3.2.a + +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Author: Oliver Walters / Currawong Engineering Pty Ltd + */ + + +#ifndef _ECUDEFINES_H +#define _ECUDEFINES_H + +// Language target is C, C++ compilers: don't mangle us +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + */ + +#include +#include "ECUProtocol.h" + +typedef struct +{ + bool servoLink; //!< 1 if CAN servo is not connected + bool servoPosition; //!< 1 if CAN servo is reporting a position error + unsigned reserved_A : 6; //!< Reserved for future use + unsigned reserved_B : 8; //!< Reserved for future use + unsigned reserved_C : 8; //!< Reserved for future use + unsigned reserved_D : 8; //!< Reserved for future use +}ECU_AuxiliaryErrorBits_t; + +//! return the minimum encoded length for the ECU_AuxiliaryErrorBits_t structure +#define getMinLengthOfECU_AuxiliaryErrorBits_t() (4) + +//! return the maximum encoded length for the ECU_AuxiliaryErrorBits_t structure +#define getMaxLengthOfECU_AuxiliaryErrorBits_t() (4) + +//! Encode a ECU_AuxiliaryErrorBits_t into a byte array +void encodeECU_AuxiliaryErrorBits_t(uint8_t* data, int* bytecount, const ECU_AuxiliaryErrorBits_t* user); + +//! Decode a ECU_AuxiliaryErrorBits_t from a byte array +int decodeECU_AuxiliaryErrorBits_t(const uint8_t* data, int* bytecount, ECU_AuxiliaryErrorBits_t* user); + +typedef struct +{ + unsigned knockControl : 1; //!< Knock control error + unsigned afCloseLoop : 1; //!< AF closed loop error + unsigned eepromError : 1; //!< EEPROM error + unsigned cmosRam : 1; //!< CMOS RAM error + unsigned overVoltage : 1; //!< Over voltage error + unsigned powerDown : 1; //!< Power down error + unsigned knockSensor : 1; //!< Knock sensor error + unsigned overBoost : 1; //!< Over boost error + unsigned cam2Pos : 1; //!< CAM2 position error + unsigned cam1Pos : 1; //!< CAM1 position error + unsigned highSpeedInput2 : 1; //!< High speed input 1 error + unsigned highSpeedInput1 : 1; //!< High speed input 2 error + unsigned tooManyCylPulse : 1; //!< Set if too many cylinder pulses + unsigned tooFewCylPulse : 1; //!< Set if too few cylinder pulses + unsigned syncInputPulseMissing : 1; //!< Set if sync input pulse missing + unsigned cylinderInputPulseMissing : 1; //!< Set if cylinder input pulse missing + unsigned af2Sensor : 1; //!< Air fuel sensor 2 error + unsigned af1Sensor : 1; //!< Air fuel sensor 1 error + unsigned baroSensor : 1; //!< Barometric pressure sensor error + unsigned ebpSensor : 1; //!< Exhaust back pressure sensor error + unsigned mapSensor : 1; //!< Manifold pressure sensor error + unsigned tpsSensor : 1; //!< Throttle position sensor error + unsigned chtSensor : 1; //!< Cylinder head temperature sensor error + unsigned matSensor : 1; //!< Manifold pressure sensor error +}ECU_AutronicErrorBits_t; + +//! return the minimum encoded length for the ECU_AutronicErrorBits_t structure +#define getMinLengthOfECU_AutronicErrorBits_t() (4) + +//! return the maximum encoded length for the ECU_AutronicErrorBits_t structure +#define getMaxLengthOfECU_AutronicErrorBits_t() (4) + +//! Encode a ECU_AutronicErrorBits_t into a byte array +void encodeECU_AutronicErrorBits_t(uint8_t* data, int* bytecount, const ECU_AutronicErrorBits_t* user); + +//! Decode a ECU_AutronicErrorBits_t from a byte array +int decodeECU_AutronicErrorBits_t(const uint8_t* data, int* bytecount, ECU_AutronicErrorBits_t* user); + +typedef struct +{ + ECU_AutronicErrorBits_t autronic; //!< Error information for autronic processor + ECU_AuxiliaryErrorBits_t auxiliary; //!< Error information for auxiliary processor +}ECU_ErrorBits_t; + +//! return the minimum encoded length for the ECU_ErrorBits_t structure +#define getMinLengthOfECU_ErrorBits_t() (8) + +//! return the maximum encoded length for the ECU_ErrorBits_t structure +#define getMaxLengthOfECU_ErrorBits_t() (8) + +//! Encode a ECU_ErrorBits_t into a byte array +void encodeECU_ErrorBits_t(uint8_t* data, int* bytecount, const ECU_ErrorBits_t* user); + +//! Decode a ECU_ErrorBits_t from a byte array +int decodeECU_ErrorBits_t(const uint8_t* data, int* bytecount, ECU_ErrorBits_t* user); + +typedef struct +{ + unsigned reserved : 7; //!< reserved for future use + bool delayOnTemp; //!< Set to base the delay on temperature, else the delay is manually set +}ECU_ThrottleDelayConfigBits_t; + +//! return the minimum encoded length for the ECU_ThrottleDelayConfigBits_t structure +#define getMinLengthOfECU_ThrottleDelayConfigBits_t() (1) + +//! return the maximum encoded length for the ECU_ThrottleDelayConfigBits_t structure +#define getMaxLengthOfECU_ThrottleDelayConfigBits_t() (1) + +//! Encode a ECU_ThrottleDelayConfigBits_t into a byte array +void encodeECU_ThrottleDelayConfigBits_t(uint8_t* data, int* bytecount, const ECU_ThrottleDelayConfigBits_t* user); + +//! Decode a ECU_ThrottleDelayConfigBits_t from a byte array +int decodeECU_ThrottleDelayConfigBits_t(const uint8_t* data, int* bytecount, ECU_ThrottleDelayConfigBits_t* user); + +typedef struct +{ + bool servoPassthrough; //!< Enable pass-through of CAN servo data over serial link + bool canThrottleDetected; //!< Set if the CAN throttle is detected + bool canThrottle; //!< Set if CAN throttle is enabled. This bit is ignored when this packet is sent to the ECU. To enable CAN throttle you must use system commands +}ECU_ThrottleConfigBits_t; + +//! return the minimum encoded length for the ECU_ThrottleConfigBits_t structure +#define getMinLengthOfECU_ThrottleConfigBits_t() (1) + +//! return the maximum encoded length for the ECU_ThrottleConfigBits_t structure +#define getMaxLengthOfECU_ThrottleConfigBits_t() (1) + +//! Encode a ECU_ThrottleConfigBits_t into a byte array +void encodeECU_ThrottleConfigBits_t(uint8_t* data, int* bytecount, const ECU_ThrottleConfigBits_t* user); + +//! Decode a ECU_ThrottleConfigBits_t from a byte array +int decodeECU_ThrottleConfigBits_t(const uint8_t* data, int* bytecount, ECU_ThrottleConfigBits_t* user); + +typedef struct +{ + bool curveActive; //!< Throttle curve is active +}ECU_ThrottleCurveConfigBits_t; + +//! return the minimum encoded length for the ECU_ThrottleCurveConfigBits_t structure +#define getMinLengthOfECU_ThrottleCurveConfigBits_t() (1) + +//! return the maximum encoded length for the ECU_ThrottleCurveConfigBits_t structure +#define getMaxLengthOfECU_ThrottleCurveConfigBits_t() (1) + +//! Encode a ECU_ThrottleCurveConfigBits_t into a byte array +void encodeECU_ThrottleCurveConfigBits_t(uint8_t* data, int* bytecount, const ECU_ThrottleCurveConfigBits_t* user); + +//! Decode a ECU_ThrottleCurveConfigBits_t from a byte array +int decodeECU_ThrottleCurveConfigBits_t(const uint8_t* data, int* bytecount, ECU_ThrottleCurveConfigBits_t* user); + +typedef struct +{ + uint16_t powerCycles; + uint16_t customerID_deprecated; //!< Deprecated - DO NOT USE + uint8_t versionHardware; + uint8_t reservedA; //!< reserved for future use + uint8_t reservedB; //!< reserved for future use +}ECU_ECUSettings_t; + +//! return the minimum encoded length for the ECU_ECUSettings_t structure +#define getMinLengthOfECU_ECUSettings_t() (7) + +//! return the maximum encoded length for the ECU_ECUSettings_t structure +#define getMaxLengthOfECU_ECUSettings_t() (7) + +//! Encode a ECU_ECUSettings_t into a byte array +void encodeECU_ECUSettings_t(uint8_t* data, int* bytecount, const ECU_ECUSettings_t* user); + +//! Decode a ECU_ECUSettings_t from a byte array +int decodeECU_ECUSettings_t(const uint8_t* data, int* bytecount, ECU_ECUSettings_t* user); + +typedef struct +{ + bool servoPassthrough; //!< If set, the ECU will pass servo CAN packet data over the serial link + bool piccoloUplink; //!< If set, the ECU will decode CAN messages in the PICCOLO_DATA_UP group + bool autronicRelay; //!< If set, the ECU supports Autronic message passthrough + bool dualPump; //!< If set, the ECU supports redundant fuel pump control + bool piPump; //!< If set, the ECU runs a PI controller for fuel pressure. If not set, it uses bang-bang control + bool mapCorrection; //!< If set, the ECU will automatically compensate for degredation of the MAP sensor over time + bool watchdog; //!< If set, the ECU watchdog timer is enabled + bool debug; //!< If set, the ECU is compiled with extra debug functionality enabled +}ECU_CompileOptions_t; + +//! return the minimum encoded length for the ECU_CompileOptions_t structure +#define getMinLengthOfECU_CompileOptions_t() (2) + +//! return the maximum encoded length for the ECU_CompileOptions_t structure +#define getMaxLengthOfECU_CompileOptions_t() (2) + +//! Encode a ECU_CompileOptions_t into a byte array +void encodeECU_CompileOptions_t(uint8_t* data, int* bytecount, const ECU_CompileOptions_t* user); + +//! Decode a ECU_CompileOptions_t from a byte array +int decodeECU_CompileOptions_t(const uint8_t* data, int* bytecount, ECU_CompileOptions_t* user); + +#ifdef __cplusplus +} +#endif +#endif // _ECUDEFINES_H diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUPackets.c b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUPackets.c new file mode 100644 index 0000000000..d3c72dc4e9 --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUPackets.c @@ -0,0 +1,4023 @@ +// ECUPackets.c was generated by ProtoGen version 3.2.a + +/* + * Copyright Currawong Engineering Pty Ltd + * www.currawongeng.com + * all rights reserved + */ + + +#include "ECUPackets.h" +#include "fielddecode.h" +#include "fieldencode.h" +#include "scaleddecode.h" +#include "scaledencode.h" + +/*! + * \brief Create the ECU_ThrottleCommand packet + * + * The throttle command packet sets the throttle position setpoint. The ECU + * will adjust the throttle position based on this command. + * \param _pg_pkt points to the packet which will be created by this function + * \param throttleCommand is Commanded throttle position in percent + */ +void encodeECU_ThrottleCommandPacket(void* _pg_pkt, float throttleCommand) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Commanded throttle position in percent + // Range of throttleCommand is 0.0f to 100.0f. + float32ScaledTo2UnsignedBeBytes(throttleCommand, _pg_data, &_pg_byteindex, 0.0f, 655.35f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ThrottleCommandPacketID()); + +}// encodeECU_ThrottleCommandPacket + +/*! + * \brief Decode the ECU_ThrottleCommand packet + * + * The throttle command packet sets the throttle position setpoint. The ECU + * will adjust the throttle position based on this command. + * \param _pg_pkt points to the packet being decoded by this function + * \param throttleCommand receives Commanded throttle position in percent + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ThrottleCommandPacket(const void* _pg_pkt, float* throttleCommand) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ThrottleCommandPacketID()) + return 0; + + if(_pg_numbytes < getECU_ThrottleCommandMinDataLength()) + return 0; + + // Commanded throttle position in percent + // Range of throttleCommand is 0.0f to 100.0f. + (*throttleCommand) = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/655.35f); + + return 1; + +}// decodeECU_ThrottleCommandPacket + +/*! + * \brief Create the ECU_RPMCommand packet + * + * The RPM command is used to send a target to the RPM governor on the ECU. + * Based on this command, the ECU will use a feedback loop to maintain the + * commanded engine speed by adjusting the throttle servo accordingly. If a + * valid RPM command is received by the ECU, it will automatically enter RPM + * control mode, and adjust the throttle position to match the desired RPM. + * Sending a throttle command will cause the ECU to stop the RPM loop and enter + * open-loop throttle control mode. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_RPMCommandPacketStructure(void* _pg_pkt, const ECU_RPMCommand_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + + // RPM command in units of 50 RPM + // Range of rpmCmdHigh is 0 to 255. + uint8ToBytes(_pg_user->rpmCmdHigh, _pg_data, &_pg_byteindex); + + // Low part of RPM command from 0 to 49 + // Range of rpmCmdLow is 0 to 255. + uint8ToBytes(_pg_user->rpmCmdLow, _pg_data, &_pg_byteindex); + + // Reconstruct the RPM command + _pg_data[0] = (uint8_t)((_pg_user->rpmCmd)/50); _pg_data[1] = (uint8_t)((_pg_user->rpmCmd) - _pg_data[0]*50); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_RPMCommandPacketID()); + +}// encodeECU_RPMCommandPacketStructure + +/*! + * \brief Decode the ECU_RPMCommand packet + * + * The RPM command is used to send a target to the RPM governor on the ECU. + * Based on this command, the ECU will use a feedback loop to maintain the + * commanded engine speed by adjusting the throttle servo accordingly. If a + * valid RPM command is received by the ECU, it will automatically enter RPM + * control mode, and adjust the throttle position to match the desired RPM. + * Sending a throttle command will cause the ECU to stop the RPM loop and enter + * open-loop throttle control mode. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_RPMCommandPacketStructure(const void* _pg_pkt, ECU_RPMCommand_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_RPMCommandPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_RPMCommandMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // RPM command in units of 50 RPM + // Range of rpmCmdHigh is 0 to 255. + _pg_user->rpmCmdHigh = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Low part of RPM command from 0 to 49 + // Range of rpmCmdLow is 0 to 255. + _pg_user->rpmCmdLow = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Reconstruct the RPM command + _pg_user->rpmCmd = (uint16_t)(_pg_user->rpmCmdHigh*50 + _pg_user->rpmCmdLow); + + return 1; + +}// decodeECU_RPMCommandPacketStructure + +/*! + * \brief Encode a ECU_ecuStatusBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_ecuStatusBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_ecuStatusBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // 1 if driver 8 is on + _pg_data[_pg_byteindex] = (uint8_t)((_pg_user->driverPin8 == true) ? 1 : 0) << 7; + + // 1 if driver 7 is on + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->driverPin7 == true) ? 1 : 0) << 6; + + // 1 if driver 2 is on + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->driverPin2 == true) ? 1 : 0) << 5; + + // 1 if driver 1 is on + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->driverPin1 == true) ? 1 : 0) << 4; + + // 1 if the throttle curve is on. + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->throttleCurveOn == true) ? 1 : 0) << 3; + + // 1 if autronic, else auxiliary. + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->rs232mode == true) ? 1 : 0) << 2; + + // 1 if any errors are set - refer to [error packet](#PKT_ECU_ERROR_MSG) + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->errorIndicator == true) ? 1 : 0) << 1; + + // Global enable based on physical input + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->enabled == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_ecuStatusBits_t + +/*! + * \brief Decode a ECU_ecuStatusBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_ecuStatusBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_ecuStatusBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // 1 if driver 8 is on + _pg_user->driverPin8 = ((_pg_data[_pg_byteindex] >> 7)) ? true : false; + + // 1 if driver 7 is on + _pg_user->driverPin7 = (((_pg_data[_pg_byteindex] >> 6) & 0x1)) ? true : false; + + // 1 if driver 2 is on + _pg_user->driverPin2 = (((_pg_data[_pg_byteindex] >> 5) & 0x1)) ? true : false; + + // 1 if driver 1 is on + _pg_user->driverPin1 = (((_pg_data[_pg_byteindex] >> 4) & 0x1)) ? true : false; + + // 1 if the throttle curve is on. + _pg_user->throttleCurveOn = (((_pg_data[_pg_byteindex] >> 3) & 0x1)) ? true : false; + + // 1 if autronic, else auxiliary. + _pg_user->rs232mode = (((_pg_data[_pg_byteindex] >> 2) & 0x1)) ? true : false; + + // 1 if any errors are set - refer to [error packet](#PKT_ECU_ERROR_MSG) + _pg_user->errorIndicator = (((_pg_data[_pg_byteindex] >> 1) & 0x1)) ? true : false; + + // Global enable based on physical input + _pg_user->enabled = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_ecuStatusBits_t + +/*! + * \brief Create the ECU_TelemetryFast packet + * + * Fast telemetry contains high priority telemetry data and is transmitted at a + * user configurable period between 50ms (20Hz) and 10s. By default, the fast + * telemetry message is transmitted at 10Hz (every 100ms) + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_TelemetryFastPacketStructure(void* _pg_pkt, const ECU_TelemetryFast_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Throttle signal (0 to 100%) + // Range of throttle is 0.0f to 100.0f. + float32ScaledTo1UnsignedBytes(_pg_user->throttle, _pg_data, &_pg_byteindex, 0.0f, 2.55f); + + // Engine speed in revolutions per minute + // Range of rpm is 0 to 65535. + uint16ToBeBytes(_pg_user->rpm, _pg_data, &_pg_byteindex); + + // Fuel used in grams + // Range of fuelUsed is 0 to 4294967295. + uint32ToBeBytes(_pg_user->fuelUsed, _pg_data, &_pg_byteindex); + + encodeECU_ecuStatusBits_t(_pg_data, &_pg_byteindex, &_pg_user->ecuStatusBits); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TelemetryFastPacketID()); + +}// encodeECU_TelemetryFastPacketStructure + +/*! + * \brief Decode the ECU_TelemetryFast packet + * + * Fast telemetry contains high priority telemetry data and is transmitted at a + * user configurable period between 50ms (20Hz) and 10s. By default, the fast + * telemetry message is transmitted at 10Hz (every 100ms) + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TelemetryFastPacketStructure(const void* _pg_pkt, ECU_TelemetryFast_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TelemetryFastPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_TelemetryFastMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Throttle signal (0 to 100%) + // Range of throttle is 0.0f to 100.0f. + _pg_user->throttle = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/2.55f); + + // Engine speed in revolutions per minute + // Range of rpm is 0 to 65535. + _pg_user->rpm = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Fuel used in grams + // Range of fuelUsed is 0 to 4294967295. + _pg_user->fuelUsed = uint32FromBeBytes(_pg_data, &_pg_byteindex); + + if(decodeECU_ecuStatusBits_t(_pg_data, &_pg_byteindex, &_pg_user->ecuStatusBits) == 0) + return 0; + + return 1; + +}// decodeECU_TelemetryFastPacketStructure + +/*! + * \brief Create the ECU_TelemetryFast packet + * + * Fast telemetry contains high priority telemetry data and is transmitted at a + * user configurable period between 50ms (20Hz) and 10s. By default, the fast + * telemetry message is transmitted at 10Hz (every 100ms) + * \param _pg_pkt points to the packet which will be created by this function + * \param throttle is Throttle signal (0 to 100%) + * \param rpm is Engine speed in revolutions per minute + * \param fuelUsed is Fuel used in grams + * \param ecuStatusBits is + */ +void encodeECU_TelemetryFastPacket(void* _pg_pkt, float throttle, uint16_t rpm, uint32_t fuelUsed, const ECU_ecuStatusBits_t* ecuStatusBits) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Throttle signal (0 to 100%) + // Range of throttle is 0.0f to 100.0f. + float32ScaledTo1UnsignedBytes(throttle, _pg_data, &_pg_byteindex, 0.0f, 2.55f); + + // Engine speed in revolutions per minute + // Range of rpm is 0 to 65535. + uint16ToBeBytes(rpm, _pg_data, &_pg_byteindex); + + // Fuel used in grams + // Range of fuelUsed is 0 to 4294967295. + uint32ToBeBytes(fuelUsed, _pg_data, &_pg_byteindex); + + encodeECU_ecuStatusBits_t(_pg_data, &_pg_byteindex, ecuStatusBits); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TelemetryFastPacketID()); + +}// encodeECU_TelemetryFastPacket + +/*! + * \brief Decode the ECU_TelemetryFast packet + * + * Fast telemetry contains high priority telemetry data and is transmitted at a + * user configurable period between 50ms (20Hz) and 10s. By default, the fast + * telemetry message is transmitted at 10Hz (every 100ms) + * \param _pg_pkt points to the packet being decoded by this function + * \param throttle receives Throttle signal (0 to 100%) + * \param rpm receives Engine speed in revolutions per minute + * \param fuelUsed receives Fuel used in grams + * \param ecuStatusBits receives + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TelemetryFastPacket(const void* _pg_pkt, float* throttle, uint16_t* rpm, uint32_t* fuelUsed, ECU_ecuStatusBits_t* ecuStatusBits) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TelemetryFastPacketID()) + return 0; + + if(_pg_numbytes < getECU_TelemetryFastMinDataLength()) + return 0; + + // Throttle signal (0 to 100%) + // Range of throttle is 0.0f to 100.0f. + (*throttle) = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/2.55f); + + // Engine speed in revolutions per minute + // Range of rpm is 0 to 65535. + (*rpm) = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Fuel used in grams + // Range of fuelUsed is 0 to 4294967295. + (*fuelUsed) = uint32FromBeBytes(_pg_data, &_pg_byteindex); + + if(decodeECU_ecuStatusBits_t(_pg_data, &_pg_byteindex, ecuStatusBits) == 0) + return 0; + + return 1; + +}// decodeECU_TelemetryFastPacket + +/*! + * \brief Create the ECU_TelemetrySlow0 packet + * + * This is the first of three slower telemetry packets which are transmitted by + * the ECU at a user customizable period (between 0.5s and 10.0s). These three + * packets contain data that is not likely to change as quickly as the data in + * the fast telemetry packet. By default, the slow telemetry messages are + * transmitted at 1Hz (period of 1.0s). + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_TelemetrySlow0PacketStructure(void* _pg_pkt, const ECU_TelemetrySlow0_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned int _pg_tempbitfield = 0; + + + + // RPM command in units of 50 RPM + uint8ToBytes((uint8_t)(0), _pg_data, &_pg_byteindex); + + // Source of the throttle information + _pg_data[_pg_byteindex] = (uint8_t)_pg_user->throttleSrc << 4; + + // Throttle pulse width in microseconds + // Range of throttlePulse is 0 to 4095. + _pg_tempbitfield = (unsigned int)limitMax(_pg_user->throttlePulse, 4095); + _pg_data[_pg_byteindex + 1] = (uint8_t)_pg_tempbitfield; + + _pg_tempbitfield >>= 8; + _pg_data[_pg_byteindex] |= (uint8_t)_pg_tempbitfield; + _pg_byteindex += 2; // close bit field + + + // Cylinder head temperature in Celsius + // Range of cht is -10.0f to 245.0f. + float32ScaledTo1UnsignedBytes(_pg_user->cht, _pg_data, &_pg_byteindex, -10.0f, 1.0f); + + // Low part of RPM command from 0 to 49 + uint8ToBytes((uint8_t)(0), _pg_data, &_pg_byteindex); + + // Barometric pressure in kilo-Pascals + // Range of baro is 0.0f to 131.07f. + float32ScaledTo2UnsignedBeBytes(_pg_user->baro, _pg_data, &_pg_byteindex, 0.0f, 500.0f); + + // Percentage ratio of manifold pressure to barometric pressure + uint8ToBytes((uint8_t)(0), _pg_data, &_pg_byteindex); + + // Reconstruct the RPM command + _pg_data[0] = (uint8_t)(_pg_user->rpmCmd/50); _pg_data[4] = (uint8_t)(_pg_user->rpmCmd - _pg_data[0]*50); + + // Reconstruct the manifold pressure + _pg_data[7] = (uint8_t)(0.5f + 100.0f*_pg_user->map/_pg_user->baro); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TelemetrySlow0PacketID()); + +}// encodeECU_TelemetrySlow0PacketStructure + +/*! + * \brief Decode the ECU_TelemetrySlow0 packet + * + * This is the first of three slower telemetry packets which are transmitted by + * the ECU at a user customizable period (between 0.5s and 10.0s). These three + * packets contain data that is not likely to change as quickly as the data in + * the fast telemetry packet. By default, the slow telemetry messages are + * transmitted at 1Hz (period of 1.0s). + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TelemetrySlow0PacketStructure(const void* _pg_pkt, ECU_TelemetrySlow0_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + unsigned int _pg_tempbitfield = 0; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TelemetrySlow0PacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_TelemetrySlow0MinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // RPM command in units of 50 RPM + _pg_byteindex += 1; + + // Source of the throttle information + _pg_user->throttleSrc = (ECUThrottleSource)(_pg_data[_pg_byteindex] >> 4); + + // Throttle pulse width in microseconds + // Range of throttlePulse is 0 to 4095. + _pg_tempbitfield = (_pg_data[_pg_byteindex] & 0xF); + + _pg_tempbitfield <<= 8; + _pg_tempbitfield |= _pg_data[_pg_byteindex + 1]; + + _pg_user->throttlePulse = _pg_tempbitfield; + _pg_byteindex += 2; // close bit field + + // Cylinder head temperature in Celsius + // Range of cht is -10.0f to 245.0f. + _pg_user->cht = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, -10.0f, 1.0f/1.0f); + + // Low part of RPM command from 0 to 49 + _pg_byteindex += 1; + + // Barometric pressure in kilo-Pascals + // Range of baro is 0.0f to 131.07f. + _pg_user->baro = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/500.0f); + + // Percentage ratio of manifold pressure to barometric pressure + _pg_byteindex += 1; + + // Reconstruct the RPM command + _pg_user->rpmCmd = (uint16_t)(_pg_data[0]*50 + _pg_data[4]); + + // Reconstruct the manifold pressure + _pg_user->map = _pg_data[7]*0.01f*_pg_user->baro; + + return 1; + +}// decodeECU_TelemetrySlow0PacketStructure + +/*! + * \brief Create the ECU_TelemetrySlow1 packet + * + * The second of three slow telemetry packets + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_TelemetrySlow1PacketStructure(void* _pg_pkt, const ECU_TelemetrySlow1_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Inlet air temperature in Celsius + // Range of mat is -127.0f to 127.0f. + float32ScaledTo1SignedBytes(_pg_user->mat, _pg_data, &_pg_byteindex, 1.0f); + + // Fuel pressure in kilo-Pascals + // Range of fuelPressure is 0.0f to 1310.7f. + float32ScaledTo2UnsignedBeBytes(_pg_user->fuelPressure, _pg_data, &_pg_byteindex, 0.0f, 50.0f); + + // Engine run time in seconds. + // Range of hobbs is 0 to 16777215. + uint24ToBeBytes((uint32_t)(limitMax(_pg_user->hobbs, 16777215)), _pg_data, &_pg_byteindex); + + // Input voltage in Volts + // Range of voltage is 0.0f to 25.5f. + float32ScaledTo1UnsignedBytes(_pg_user->voltage, _pg_data, &_pg_byteindex, 0.0f, 10.0f); + + _pg_data[_pg_byteindex] = 0; + + // Operational mode of the governor + _pg_data[_pg_byteindex] |= (uint8_t)_pg_user->governorMode; + _pg_byteindex += 1; // close bit field + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TelemetrySlow1PacketID()); + +}// encodeECU_TelemetrySlow1PacketStructure + +/*! + * \brief Decode the ECU_TelemetrySlow1 packet + * + * The second of three slow telemetry packets + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TelemetrySlow1PacketStructure(const void* _pg_pkt, ECU_TelemetrySlow1_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TelemetrySlow1PacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_TelemetrySlow1MinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Inlet air temperature in Celsius + // Range of mat is -127.0f to 127.0f. + _pg_user->mat = float32ScaledFrom1SignedBytes(_pg_data, &_pg_byteindex, 1.0f/1.0f); + + // Fuel pressure in kilo-Pascals + // Range of fuelPressure is 0.0f to 1310.7f. + _pg_user->fuelPressure = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/50.0f); + + // Engine run time in seconds. + // Range of hobbs is 0 to 16777215. + _pg_user->hobbs = (uint32_t)uint24FromBeBytes(_pg_data, &_pg_byteindex); + + // Input voltage in Volts + // Range of voltage is 0.0f to 25.5f. + _pg_user->voltage = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/10.0f); + + // Operational mode of the governor + _pg_user->governorMode = (ECUGovernorMode)((_pg_data[_pg_byteindex]) & 0x7); + _pg_byteindex += 1; // close bit field + + return 1; + +}// decodeECU_TelemetrySlow1PacketStructure + +/*! + * \brief Create the ECU_TelemetrySlow2 packet + * + * The third of three slow telemetry packets + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_TelemetrySlow2PacketStructure(void* _pg_pkt, const ECU_TelemetrySlow2_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // CPU load in percent + // Range of cpuLoad is 0.0f to 255.0f. + float32ScaledTo1UnsignedBytes(_pg_user->cpuLoad, _pg_data, &_pg_byteindex, 0.0f, 1.0f); + + // Charge temperature in Celsius + // Range of chargeTemp is -128.0f to 254.5f. + float32ScaledTo1UnsignedBytes(_pg_user->chargeTemp, _pg_data, &_pg_byteindex, -128.0f, 0.666666667f); + + // Injector duty cycle in percent + // Range of injectorDuty is 0.0f to 6553.5f. + float32ScaledTo2UnsignedBeBytes(_pg_user->injectorDuty, _pg_data, &_pg_byteindex, 0.0f, 10.0f); + + // First ignition advance angle in degrees + // Range of ignAngle1 is 0.0f to 127.5f. + float32ScaledTo1UnsignedBytes(_pg_user->ignAngle1, _pg_data, &_pg_byteindex, 0.0f, 2.0f); + + // Second ignition advance angle in degrees + // Range of ignAngle2 is 0.0f to 127.5f. + float32ScaledTo1UnsignedBytes(_pg_user->ignAngle2, _pg_data, &_pg_byteindex, 0.0f, 2.0f); + + // Fuel flow rate in grams per minute + // Range of flowRate is 0.0f to 1092.25f. + float32ScaledTo2UnsignedBeBytes(_pg_user->flowRate, _pg_data, &_pg_byteindex, 0.0f, 60.0f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TelemetrySlow2PacketID()); + +}// encodeECU_TelemetrySlow2PacketStructure + +/*! + * \brief Decode the ECU_TelemetrySlow2 packet + * + * The third of three slow telemetry packets + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TelemetrySlow2PacketStructure(const void* _pg_pkt, ECU_TelemetrySlow2_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TelemetrySlow2PacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_TelemetrySlow2MinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // CPU load in percent + // Range of cpuLoad is 0.0f to 255.0f. + _pg_user->cpuLoad = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1.0f); + + // Charge temperature in Celsius + // Range of chargeTemp is -128.0f to 254.5f. + _pg_user->chargeTemp = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, -128.0f, 1.0f/0.666666667f); + + // Injector duty cycle in percent + // Range of injectorDuty is 0.0f to 6553.5f. + _pg_user->injectorDuty = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/10.0f); + + // First ignition advance angle in degrees + // Range of ignAngle1 is 0.0f to 127.5f. + _pg_user->ignAngle1 = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/2.0f); + + // Second ignition advance angle in degrees + // Range of ignAngle2 is 0.0f to 127.5f. + _pg_user->ignAngle2 = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/2.0f); + + // Fuel flow rate in grams per minute + // Range of flowRate is 0.0f to 1092.25f. + _pg_user->flowRate = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/60.0f); + + return 1; + +}// decodeECU_TelemetrySlow2PacketStructure + +/*! + * \brief Create the ECU_HardwareConfig packet + * + * The hardware config packet contains the ECU serial number and various ECU + * configuration data. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_HardwareConfigPacketStructure(void* _pg_pkt, const ECU_HardwareConfig_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // ECU serial number + // Range of serialNumber is 0 to 65535. + uint16ToBeBytes(_pg_user->serialNumber, _pg_data, &_pg_byteindex); + + // Fuel used divisior. If the divisor is greater than 100 then it is interpreted as units of 0.01 (for a higher resolution fuel calibration) + // Range of fuelDivisor is 0 to 65535. + uint16ToBeBytes(_pg_user->fuelDivisor, _pg_data, &_pg_byteindex); + + _pg_data[_pg_byteindex] = 0; + + // Autronic relay state. This is a volatile status which will reset to AUT_RELAY_OFF on ECU power cycle. + _pg_data[_pg_byteindex] |= (uint8_t)_pg_user->relayState << 1; + + // Set if the fuel used value is reset each on each ECU power cycle + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->resetFuelUsedOnStart == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_HardwareConfigPacketID()); + +}// encodeECU_HardwareConfigPacketStructure + +/*! + * \brief Decode the ECU_HardwareConfig packet + * + * The hardware config packet contains the ECU serial number and various ECU + * configuration data. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_HardwareConfigPacketStructure(const void* _pg_pkt, ECU_HardwareConfig_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_HardwareConfigPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_HardwareConfigMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // ECU serial number + // Range of serialNumber is 0 to 65535. + _pg_user->serialNumber = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Fuel used divisior. If the divisor is greater than 100 then it is interpreted as units of 0.01 (for a higher resolution fuel calibration) + // Range of fuelDivisor is 0 to 65535. + _pg_user->fuelDivisor = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Autronic relay state. This is a volatile status which will reset to AUT_RELAY_OFF on ECU power cycle. + _pg_user->relayState = (ECUAutronicRelayState)((_pg_data[_pg_byteindex] >> 1) & 0x3); + + // Set if the fuel used value is reset each on each ECU power cycle + _pg_user->resetFuelUsedOnStart = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + return 1; + +}// decodeECU_HardwareConfigPacketStructure + +/*! + * \brief Create the ECU_Version packet + * + * The software version packet contains the auxiliary processor firmware + * version information. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_VersionPacketStructure(void* _pg_pkt, const ECU_Version_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // 1 = Release version, 0 = Testing version + _pg_data[_pg_byteindex] = (uint8_t)((_pg_user->release == true) ? 1 : 0) << 7; + + // Reserved for future use + + // Major version number + // Range of versionMajor is 0 to 63. + _pg_data[_pg_byteindex] |= (uint8_t)_pg_user->versionMajor; + _pg_byteindex += 1; // close bit field + + + // Minor version number + // Range of versionMinor is 0 to 255. + uint8ToBytes(_pg_user->versionMinor, _pg_data, &_pg_byteindex); + + // Revision number + // Range of versionRev is 0 to 15. + _pg_data[_pg_byteindex] = (uint8_t)limitMax(_pg_user->versionRev, 15) << 4; + + // The release month from 1 (January) to 12 (December) + // Range of month is 0 to 15. + _pg_data[_pg_byteindex] |= (uint8_t)limitMax(_pg_user->month, 15); + _pg_byteindex += 1; // close bit field + + + // The release day of month from 1 to 31 + // Range of day is 0 to 255. + uint8ToBytes(_pg_user->day, _pg_data, &_pg_byteindex); + + // The release year + // Range of year is 0 to 65535. + uint16ToBeBytes(_pg_user->year, _pg_data, &_pg_byteindex); + + // Firmware checksum + // Range of checksum is 0 to 65535. + uint16ToBeBytes(_pg_user->checksum, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_VersionPacketID()); + +}// encodeECU_VersionPacketStructure + +/*! + * \brief Decode the ECU_Version packet + * + * The software version packet contains the auxiliary processor firmware + * version information. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_VersionPacketStructure(const void* _pg_pkt, ECU_Version_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_VersionPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_VersionMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // 1 = Release version, 0 = Testing version + _pg_user->release = ((_pg_data[_pg_byteindex] >> 7)) ? true : false; + + // Reserved for future use + + // Major version number + // Range of versionMajor is 0 to 63. + _pg_user->versionMajor = ((_pg_data[_pg_byteindex]) & 0x3F); + _pg_byteindex += 1; // close bit field + + // Minor version number + // Range of versionMinor is 0 to 255. + _pg_user->versionMinor = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Revision number + // Range of versionRev is 0 to 15. + _pg_user->versionRev = (_pg_data[_pg_byteindex] >> 4); + + // The release month from 1 (January) to 12 (December) + // Range of month is 0 to 15. + _pg_user->month = ((_pg_data[_pg_byteindex]) & 0xF); + _pg_byteindex += 1; // close bit field + + // The release day of month from 1 to 31 + // Range of day is 0 to 255. + _pg_user->day = uint8FromBytes(_pg_data, &_pg_byteindex); + + // The release year + // Range of year is 0 to 65535. + _pg_user->year = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Firmware checksum + // Range of checksum is 0 to 65535. + _pg_user->checksum = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_VersionPacketStructure + +/*! + * \brief Create the ECU_Errors packet + * + * The errors packet contains error status information for the ECU. If any + * error bits are set, then the global error bit in the [fast + * telemetry](#PKT_ECU_TELEMETRY_FAST) packet will also be set. Send a zero + * length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_ErrorsPacketStructure(void* _pg_pkt, const ECU_Errors_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Error bits for the Autronic processor + encodeECU_AutronicErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->autronicErrors); + + // Error bits for the auxiliary processor + encodeECU_AuxiliaryErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->auxiliaryErrors); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ErrorsPacketID()); + +}// encodeECU_ErrorsPacketStructure + +/*! + * \brief Decode the ECU_Errors packet + * + * The errors packet contains error status information for the ECU. If any + * error bits are set, then the global error bit in the [fast + * telemetry](#PKT_ECU_TELEMETRY_FAST) packet will also be set. Send a zero + * length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ErrorsPacketStructure(const void* _pg_pkt, ECU_Errors_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ErrorsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_ErrorsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Error bits for the Autronic processor + if(decodeECU_AutronicErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->autronicErrors) == 0) + return 0; + + // Error bits for the auxiliary processor + if(decodeECU_AuxiliaryErrorBits_t(_pg_data, &_pg_byteindex, &_pg_user->auxiliaryErrors) == 0) + return 0; + + return 1; + +}// decodeECU_ErrorsPacketStructure + +/*! + * \brief Create the ECU_PowerCycles packet + * + * The power cycles packet contains information on the reset condition of the + * ECU. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_PowerCyclesPacketStructure(void* _pg_pkt, const ECU_PowerCycles_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Number of power cycles + // Range of powerCycles is 0 to 65535. + uint16ToBeBytes(_pg_user->powerCycles, _pg_data, &_pg_byteindex); + + // Range of reserved is 0 to 255. + uint8ToBytes(_pg_user->reserved, _pg_data, &_pg_byteindex); + + // Auxiliary processor reset code + // Range of resetCode is 0 to 255. + uint8ToBytes(_pg_user->resetCode, _pg_data, &_pg_byteindex); + + // Milliseconds since system reset + // Range of systemTime is 0 to 4294967295. + uint32ToBeBytes(_pg_user->systemTime, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_PowerCyclesPacketID()); + +}// encodeECU_PowerCyclesPacketStructure + +/*! + * \brief Decode the ECU_PowerCycles packet + * + * The power cycles packet contains information on the reset condition of the + * ECU. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_PowerCyclesPacketStructure(const void* _pg_pkt, ECU_PowerCycles_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_PowerCyclesPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_PowerCyclesMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Number of power cycles + // Range of powerCycles is 0 to 65535. + _pg_user->powerCycles = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of reserved is 0 to 255. + _pg_user->reserved = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Auxiliary processor reset code + // Range of resetCode is 0 to 255. + _pg_user->resetCode = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Milliseconds since system reset + // Range of systemTime is 0 to 4294967295. + _pg_user->systemTime = uint32FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_PowerCyclesPacketStructure + +/*! + * \brief Create the ECU_PumpDebug packet + * + * The fuel pump debug packet contains information on the pump control system. + * Send a zero length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_PumpDebugPacketStructure(void* _pg_pkt, const ECU_PumpDebug_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Proportional term of the pump feedback control in percent + // Range of pTerm is -3276.7f to 3276.7f. + float32ScaledTo2SignedBeBytes(_pg_user->pTerm, _pg_data, &_pg_byteindex, 10.0f); + + // Integral term of the pump feedback control in percent + // Range of iTerm is -3276.7f to 3276.7f. + float32ScaledTo2SignedBeBytes(_pg_user->iTerm, _pg_data, &_pg_byteindex, 10.0f); + + // Pump duty cycle in percent + // Range of dutyCycle is 0.0f to 6553.5f. + float32ScaledTo2UnsignedBeBytes(_pg_user->dutyCycle, _pg_data, &_pg_byteindex, 0.0f, 10.0f); + + // Fuel pressure in kilo-Pascals + // Range of fuelPressure is 0.0f to 1310.7f. + float32ScaledTo2UnsignedBeBytes(_pg_user->fuelPressure, _pg_data, &_pg_byteindex, 0.0f, 50.0f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_PumpDebugPacketID()); + +}// encodeECU_PumpDebugPacketStructure + +/*! + * \brief Decode the ECU_PumpDebug packet + * + * The fuel pump debug packet contains information on the pump control system. + * Send a zero length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_PumpDebugPacketStructure(const void* _pg_pkt, ECU_PumpDebug_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_PumpDebugPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_PumpDebugMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Proportional term of the pump feedback control in percent + // Range of pTerm is -3276.7f to 3276.7f. + _pg_user->pTerm = float32ScaledFrom2SignedBeBytes(_pg_data, &_pg_byteindex, 1.0f/10.0f); + + // Integral term of the pump feedback control in percent + // Range of iTerm is -3276.7f to 3276.7f. + _pg_user->iTerm = float32ScaledFrom2SignedBeBytes(_pg_data, &_pg_byteindex, 1.0f/10.0f); + + // Pump duty cycle in percent + // Range of dutyCycle is 0.0f to 6553.5f. + _pg_user->dutyCycle = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/10.0f); + + // Fuel pressure in kilo-Pascals + // Range of fuelPressure is 0.0f to 1310.7f. + _pg_user->fuelPressure = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/50.0f); + + return 1; + +}// decodeECU_PumpDebugPacketStructure + +/*! + * \brief Create the ECU_TotalEngineTime packet + * + * While the engine time contained in the ECU telemetry packet can be reset by + * the user, the ECU also stores the total engine time, which cannot be reset + * by the user. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param hobbs is Total engine run time in seconds + */ +void encodeECU_TotalEngineTimePacket(void* _pg_pkt, uint32_t hobbs) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Total engine run time in seconds + // Range of hobbs is 0 to 16777215. + uint24ToBeBytes((uint32_t)(limitMax(hobbs, 16777215)), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TotalEngineTimePacketID()); + +}// encodeECU_TotalEngineTimePacket + +/*! + * \brief Decode the ECU_TotalEngineTime packet + * + * While the engine time contained in the ECU telemetry packet can be reset by + * the user, the ECU also stores the total engine time, which cannot be reset + * by the user. Send a zero length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param hobbs receives Total engine run time in seconds + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TotalEngineTimePacket(const void* _pg_pkt, uint32_t* hobbs) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TotalEngineTimePacketID()) + return 0; + + if(_pg_numbytes < getECU_TotalEngineTimeMinDataLength()) + return 0; + + // Total engine run time in seconds + // Range of hobbs is 0 to 16777215. + (*hobbs) = (uint32_t)uint24FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_TotalEngineTimePacket + +/*! + * \brief Create the ECU_eepromSettings packet + * + * The eeprom settings packet contains information on the non-volatile ECU + * settings stored in eeprom. In particular, it provides a checksum of the + * settings data for easy comparison of settings between different ECUs. Send a + * zero length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_eepromSettingsPacketStructure(void* _pg_pkt, const ECU_eepromSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Version of the EEPROM data + // Range of eepromVersion is 0 to 255. + uint8ToBytes(_pg_user->eepromVersion, _pg_data, &_pg_byteindex); + + // Number of bytes of the EEPROM data + // Range of eepromSize is 0 to 65535. + uint16ToBeBytes(_pg_user->eepromSize, _pg_data, &_pg_byteindex); + + // Fletcher's checksum of the EEPROM data + // Range of eepromChecksum is 0 to 65535. + uint16ToBeBytes(_pg_user->eepromChecksum, _pg_data, &_pg_byteindex); + + // ECU compilation options + encodeECU_CompileOptions_t(_pg_data, &_pg_byteindex, &_pg_user->compileOptions); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_eepromSettingsPacketID()); + +}// encodeECU_eepromSettingsPacketStructure + +/*! + * \brief Decode the ECU_eepromSettings packet + * + * The eeprom settings packet contains information on the non-volatile ECU + * settings stored in eeprom. In particular, it provides a checksum of the + * settings data for easy comparison of settings between different ECUs. Send a + * zero length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_eepromSettingsPacketStructure(const void* _pg_pkt, ECU_eepromSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_eepromSettingsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_eepromSettingsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Version of the EEPROM data + // Range of eepromVersion is 0 to 255. + _pg_user->eepromVersion = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Number of bytes of the EEPROM data + // Range of eepromSize is 0 to 65535. + _pg_user->eepromSize = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Fletcher's checksum of the EEPROM data + // Range of eepromChecksum is 0 to 65535. + _pg_user->eepromChecksum = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // ECU compilation options + if(decodeECU_CompileOptions_t(_pg_data, &_pg_byteindex, &_pg_user->compileOptions) == 0) + return 0; + + return 1; + +}// decodeECU_eepromSettingsPacketStructure + +/*! + * \brief Create the ECU_eepromSettings packet + * + * The eeprom settings packet contains information on the non-volatile ECU + * settings stored in eeprom. In particular, it provides a checksum of the + * settings data for easy comparison of settings between different ECUs. Send a + * zero length packet to request this data. + * \param _pg_pkt points to the packet which will be created by this function + * \param eepromVersion is Version of the EEPROM data + * \param eepromSize is Number of bytes of the EEPROM data + * \param eepromChecksum is Fletcher's checksum of the EEPROM data + * \param compileOptions is ECU compilation options + */ +void encodeECU_eepromSettingsPacket(void* _pg_pkt, uint8_t eepromVersion, uint16_t eepromSize, uint16_t eepromChecksum, const ECU_CompileOptions_t* compileOptions) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Version of the EEPROM data + // Range of eepromVersion is 0 to 255. + uint8ToBytes(eepromVersion, _pg_data, &_pg_byteindex); + + // Number of bytes of the EEPROM data + // Range of eepromSize is 0 to 65535. + uint16ToBeBytes(eepromSize, _pg_data, &_pg_byteindex); + + // Fletcher's checksum of the EEPROM data + // Range of eepromChecksum is 0 to 65535. + uint16ToBeBytes(eepromChecksum, _pg_data, &_pg_byteindex); + + // ECU compilation options + encodeECU_CompileOptions_t(_pg_data, &_pg_byteindex, compileOptions); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_eepromSettingsPacketID()); + +}// encodeECU_eepromSettingsPacket + +/*! + * \brief Decode the ECU_eepromSettings packet + * + * The eeprom settings packet contains information on the non-volatile ECU + * settings stored in eeprom. In particular, it provides a checksum of the + * settings data for easy comparison of settings between different ECUs. Send a + * zero length packet to request this data. + * \param _pg_pkt points to the packet being decoded by this function + * \param eepromVersion receives Version of the EEPROM data + * \param eepromSize receives Number of bytes of the EEPROM data + * \param eepromChecksum receives Fletcher's checksum of the EEPROM data + * \param compileOptions receives ECU compilation options + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_eepromSettingsPacket(const void* _pg_pkt, uint8_t* eepromVersion, uint16_t* eepromSize, uint16_t* eepromChecksum, ECU_CompileOptions_t* compileOptions) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_eepromSettingsPacketID()) + return 0; + + if(_pg_numbytes < getECU_eepromSettingsMinDataLength()) + return 0; + + // Version of the EEPROM data + // Range of eepromVersion is 0 to 255. + (*eepromVersion) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Number of bytes of the EEPROM data + // Range of eepromSize is 0 to 65535. + (*eepromSize) = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Fletcher's checksum of the EEPROM data + // Range of eepromChecksum is 0 to 65535. + (*eepromChecksum) = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // ECU compilation options + if(decodeECU_CompileOptions_t(_pg_data, &_pg_byteindex, compileOptions) == 0) + return 0; + + return 1; + +}// decodeECU_eepromSettingsPacket + +/*! + * \brief Create the ECU_CHTLoopSettings packet + * + * Control loop settings for the CHT control loop + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_CHTLoopSettingsPacketStructure(void* _pg_pkt, const ECU_CHTLoopSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + _pg_data[_pg_byteindex] = 0; + + // Filter value for derivative term + // Range of dTermFilter is 0 to 31. + _pg_data[_pg_byteindex] |= (uint8_t)limitMax(_pg_user->dTermFilter, 31) << 1; + + // CHT control loop enabled + _pg_data[_pg_byteindex] |= (uint8_t)((_pg_user->enabled == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + + // Target CHT temperature + // Range of targetTemp is 0 to 255. + uint8ToBytes(_pg_user->targetTemp, _pg_data, &_pg_byteindex); + + // Proportaional gain Kp + // Range of Kp is 0.0f to 65.535f. + float32ScaledTo2UnsignedBeBytes(_pg_user->Kp, _pg_data, &_pg_byteindex, 0.0f, 1000.0f); + + // Proportaional gain Ki + // Range of Ki is 0.0f to 65.535f. + float32ScaledTo2UnsignedBeBytes(_pg_user->Ki, _pg_data, &_pg_byteindex, 0.0f, 1000.0f); + + // Proportaional gain Kd + // Range of Kd is 0.0f to 65.535f. + float32ScaledTo2UnsignedBeBytes(_pg_user->Kd, _pg_data, &_pg_byteindex, 0.0f, 1000.0f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_CHTLoopSettingsPacketID()); + +}// encodeECU_CHTLoopSettingsPacketStructure + +/*! + * \brief Decode the ECU_CHTLoopSettings packet + * + * Control loop settings for the CHT control loop + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_CHTLoopSettingsPacketStructure(const void* _pg_pkt, ECU_CHTLoopSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_CHTLoopSettingsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_CHTLoopSettingsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Filter value for derivative term + // Range of dTermFilter is 0 to 31. + _pg_user->dTermFilter = ((_pg_data[_pg_byteindex] >> 1) & 0x1F); + + // CHT control loop enabled + _pg_user->enabled = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + // Target CHT temperature + // Range of targetTemp is 0 to 255. + _pg_user->targetTemp = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Proportaional gain Kp + // Range of Kp is 0.0f to 65.535f. + _pg_user->Kp = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1000.0f); + + // Proportaional gain Ki + // Range of Ki is 0.0f to 65.535f. + _pg_user->Ki = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1000.0f); + + // Proportaional gain Kd + // Range of Kd is 0.0f to 65.535f. + _pg_user->Kd = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1000.0f); + + return 1; + +}// decodeECU_CHTLoopSettingsPacketStructure + +/*! + * \brief Create the ECU_CHTLoopSettings packet + * + * Control loop settings for the CHT control loop + * \param _pg_pkt points to the packet which will be created by this function + * \param dTermFilter is Filter value for derivative term + * \param enabled is CHT control loop enabled + * \param targetTemp is Target CHT temperature + * \param Kp is Proportaional gain Kp + * \param Ki is Proportaional gain Ki + * \param Kd is Proportaional gain Kd + */ +void encodeECU_CHTLoopSettingsPacket(void* _pg_pkt, uint8_t dTermFilter, bool enabled, uint8_t targetTemp, float Kp, float Ki, float Kd) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + _pg_data[_pg_byteindex] = 0; + + // Filter value for derivative term + // Range of dTermFilter is 0 to 31. + _pg_data[_pg_byteindex] |= (uint8_t)limitMax(dTermFilter, 31) << 1; + + // CHT control loop enabled + _pg_data[_pg_byteindex] |= (uint8_t)((enabled == true) ? 1 : 0); + _pg_byteindex += 1; // close bit field + + // Target CHT temperature + // Range of targetTemp is 0 to 255. + uint8ToBytes(targetTemp, _pg_data, &_pg_byteindex); + + // Proportaional gain Kp + // Range of Kp is 0.0f to 65.535f. + float32ScaledTo2UnsignedBeBytes(Kp, _pg_data, &_pg_byteindex, 0.0f, 1000.0f); + + // Proportaional gain Ki + // Range of Ki is 0.0f to 65.535f. + float32ScaledTo2UnsignedBeBytes(Ki, _pg_data, &_pg_byteindex, 0.0f, 1000.0f); + + // Proportaional gain Kd + // Range of Kd is 0.0f to 65.535f. + float32ScaledTo2UnsignedBeBytes(Kd, _pg_data, &_pg_byteindex, 0.0f, 1000.0f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_CHTLoopSettingsPacketID()); + +}// encodeECU_CHTLoopSettingsPacket + +/*! + * \brief Decode the ECU_CHTLoopSettings packet + * + * Control loop settings for the CHT control loop + * \param _pg_pkt points to the packet being decoded by this function + * \param dTermFilter receives Filter value for derivative term + * \param enabled receives CHT control loop enabled + * \param targetTemp receives Target CHT temperature + * \param Kp receives Proportaional gain Kp + * \param Ki receives Proportaional gain Ki + * \param Kd receives Proportaional gain Kd + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_CHTLoopSettingsPacket(const void* _pg_pkt, uint8_t* dTermFilter, bool* enabled, uint8_t* targetTemp, float* Kp, float* Ki, float* Kd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_CHTLoopSettingsPacketID()) + return 0; + + if(_pg_numbytes < getECU_CHTLoopSettingsMinDataLength()) + return 0; + + // Filter value for derivative term + // Range of dTermFilter is 0 to 31. + (*dTermFilter) = ((_pg_data[_pg_byteindex] >> 1) & 0x1F); + + // CHT control loop enabled + (*enabled) = (((_pg_data[_pg_byteindex]) & 0x1)) ? true : false; + _pg_byteindex += 1; // close bit field + + // Target CHT temperature + // Range of targetTemp is 0 to 255. + (*targetTemp) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Proportaional gain Kp + // Range of Kp is 0.0f to 65.535f. + (*Kp) = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1000.0f); + + // Proportaional gain Ki + // Range of Ki is 0.0f to 65.535f. + (*Ki) = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1000.0f); + + // Proportaional gain Kd + // Range of Kd is 0.0f to 65.535f. + (*Kd) = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1000.0f); + + return 1; + +}// decodeECU_CHTLoopSettingsPacket + +/*! + * \brief Create the ECU_DualPumpControlTelemetry packet + * + * Dual pump control telemetry. Send a zero-length packet with this identifier + * to the ECU to poll (request) this packet. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_DualPumpControlTelemetryPacketStructure(void* _pg_pkt, const ECU_DualPumpControlTelemetry_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + uint8ToBytes((uint8_t)(0xBB), _pg_data, &_pg_byteindex); + + // Current pump mode (which pump is running). Refer to the DualFuelPumpMode enumeration. + // Range of mode is 0 to 7. + _pg_data[_pg_byteindex] = (uint8_t)limitMax(_pg_user->mode, 7) << 5; + + // Current pump state machine state. Refer to the DualFuelPumpState enumeration. + // Range of state is 0 to 7. + _pg_data[_pg_byteindex] |= (uint8_t)limitMax(_pg_user->state, 7) << 2; + _pg_byteindex += 1; // close bit field + + + // Time spent in current state + // Range of stateTimer is 0 to 65535. + uint16ToBeBytes(_pg_user->stateTimer, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_DualPumpControlTelemetryPacketID()); + +}// encodeECU_DualPumpControlTelemetryPacketStructure + +/*! + * \brief Decode the ECU_DualPumpControlTelemetry packet + * + * Dual pump control telemetry. Send a zero-length packet with this identifier + * to the ECU to poll (request) this packet. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_DualPumpControlTelemetryPacketStructure(const void* _pg_pkt, ECU_DualPumpControlTelemetry_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_DualPumpControlTelemetryPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_DualPumpControlTelemetryMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) 0xBB) + return 0; + + // Current pump mode (which pump is running). Refer to the DualFuelPumpMode enumeration. + // Range of mode is 0 to 7. + _pg_user->mode = (_pg_data[_pg_byteindex] >> 5); + + // Current pump state machine state. Refer to the DualFuelPumpState enumeration. + // Range of state is 0 to 7. + _pg_user->state = ((_pg_data[_pg_byteindex] >> 2) & 0x7); + _pg_byteindex += 1; // close bit field + + // Time spent in current state + // Range of stateTimer is 0 to 65535. + _pg_user->stateTimer = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_DualPumpControlTelemetryPacketStructure + +/*! + * \brief Create the ECU_DualPump_SetTelemetryPeriod packet + * + * Set the telemetry period for dual-pump messages + * \param _pg_pkt points to the packet which will be created by this function + * \param period is Telemetry period (0 = Off) + */ +void encodeECU_DualPump_SetTelemetryPeriodPacket(void* _pg_pkt, uint8_t period) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + uint8ToBytes((uint8_t)(0xBB), _pg_data, &_pg_byteindex); + + // Telemetry period (0 = Off) + // Range of period is 0 to 255. + uint8ToBytes(period, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_DualPump_SetTelemetryPeriodPacketID()); + +}// encodeECU_DualPump_SetTelemetryPeriodPacket + +/*! + * \brief Decode the ECU_DualPump_SetTelemetryPeriod packet + * + * Set the telemetry period for dual-pump messages + * \param _pg_pkt points to the packet being decoded by this function + * \param period receives Telemetry period (0 = Off) + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_DualPump_SetTelemetryPeriodPacket(const void* _pg_pkt, uint8_t* period) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_DualPump_SetTelemetryPeriodPacketID()) + return 0; + + if(_pg_numbytes < getECU_DualPump_SetTelemetryPeriodMinDataLength()) + return 0; + + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) 0xBB) + return 0; + + // Telemetry period (0 = Off) + // Range of period is 0 to 255. + (*period) = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_DualPump_SetTelemetryPeriodPacket + +/*! + * \brief Create the ECU_DualPump_SelectPump packet + * + * Command to manually select a given pump mode. + * \param _pg_pkt points to the packet which will be created by this function + * \param pump is Pump selection (see DualFuelPumpMode enumeration) + */ +void encodeECU_DualPump_SelectPumpPacket(void* _pg_pkt, uint8_t pump) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + uint8ToBytes((uint8_t)(0xCC), _pg_data, &_pg_byteindex); + + uint8ToBytes((uint8_t)(ECU_DUAL_PUMP_CMD_SET_PUMP), _pg_data, &_pg_byteindex); + + // Pump selection (see DualFuelPumpMode enumeration) + // Range of pump is 0 to 255. + uint8ToBytes(pump, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_DualPump_SelectPumpPacketID()); + +}// encodeECU_DualPump_SelectPumpPacket + +/*! + * \brief Decode the ECU_DualPump_SelectPump packet + * + * Command to manually select a given pump mode. + * \param _pg_pkt points to the packet being decoded by this function + * \param pump receives Pump selection (see DualFuelPumpMode enumeration) + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_DualPump_SelectPumpPacket(const void* _pg_pkt, uint8_t* pump) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_DualPump_SelectPumpPacketID()) + return 0; + + if(_pg_numbytes < getECU_DualPump_SelectPumpMinDataLength()) + return 0; + + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) 0xCC) + return 0; + + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) ECU_DUAL_PUMP_CMD_SET_PUMP) + return 0; + + // Pump selection (see DualFuelPumpMode enumeration) + // Range of pump is 0 to 255. + (*pump) = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_DualPump_SelectPumpPacket + +/*! + * \brief Create the ECU_DualPump_TestPump packet + * + * Command to temporarily run a particular pump in test mode. ECU will revert + * to OTHER pump when test expires + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_DualPump_TestPumpPacketStructure(void* _pg_pkt, const ECU_DualPump_TestPump_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + uint8ToBytes((uint8_t)(0xCC), _pg_data, &_pg_byteindex); + + uint8ToBytes((uint8_t)(ECU_DUAL_PUMP_CMD_TEST_PUMP), _pg_data, &_pg_byteindex); + + // Pump selection (see DualFuelPumpMode enumeration) + // Range of pump is 0 to 255. + uint8ToBytes(_pg_user->pump, _pg_data, &_pg_byteindex); + + // Test timeout + // Range of timeout is 0 to 255. + uint8ToBytes(_pg_user->timeout, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_DualPump_TestPumpPacketID()); + +}// encodeECU_DualPump_TestPumpPacketStructure + +/*! + * \brief Decode the ECU_DualPump_TestPump packet + * + * Command to temporarily run a particular pump in test mode. ECU will revert + * to OTHER pump when test expires + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_DualPump_TestPumpPacketStructure(const void* _pg_pkt, ECU_DualPump_TestPump_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_DualPump_TestPumpPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_DualPump_TestPumpMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // this packet has default fields, make sure they are set + _pg_user->timeout = 30; + + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) 0xCC) + return 0; + + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) ECU_DUAL_PUMP_CMD_TEST_PUMP) + return 0; + + // Pump selection (see DualFuelPumpMode enumeration) + // Range of pump is 0 to 255. + _pg_user->pump = uint8FromBytes(_pg_data, &_pg_byteindex); + + if(_pg_byteindex + 1 > _pg_numbytes) + return 1; + + // Test timeout + // Range of timeout is 0 to 255. + _pg_user->timeout = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_DualPump_TestPumpPacketStructure + +/*! + * \brief Create the ECU_ThrottleCalibration packet + * + * The throttle calibration packet sets the calibration values for minimum and + * maximum throttle position. The ECU uses these values to interpolate the + * throttle command. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_ThrottleCalibrationPacketStructure(void* _pg_pkt, const ECU_ThrottleSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned int _pg_tempbitfield = 0; + + // Output position for 0% throttle in microseconds + // Range of pulseClosed is 0 to 65535. + uint16ToBeBytes(_pg_user->pulseClosed, _pg_data, &_pg_byteindex); + + // Output position for 100% throttle in microseconds + // Range of pulseOpen is 0 to 65535. + uint16ToBeBytes(_pg_user->pulseOpen, _pg_data, &_pg_byteindex); + + // Throttle configuration settings + encodeECU_ThrottleConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->config); + + // Input PWM in microseconds for 0% throttle + // Range of pulseInputClosed is 0 to 4095. + _pg_tempbitfield = (unsigned int)limitMax(_pg_user->pulseInputClosed, 4095); + _pg_data[_pg_byteindex + 1] = (uint8_t)(_pg_tempbitfield << 4); + + _pg_tempbitfield >>= 4; + _pg_data[_pg_byteindex] = (uint8_t)_pg_tempbitfield; + + + // Input PWM in microseconds for 100% throttle + // Range of pulseInputOpen is 0 to 4095. + _pg_tempbitfield = (unsigned int)limitMax(_pg_user->pulseInputOpen, 4095); + _pg_data[_pg_byteindex + 2] = (uint8_t)_pg_tempbitfield; + + _pg_tempbitfield >>= 8; + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_tempbitfield; + _pg_byteindex += 3; // close bit field + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ThrottleCalibrationPacketID()); + +}// encodeECU_ThrottleCalibrationPacketStructure + +/*! + * \brief Decode the ECU_ThrottleCalibration packet + * + * The throttle calibration packet sets the calibration values for minimum and + * maximum throttle position. The ECU uses these values to interpolate the + * throttle command. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ThrottleCalibrationPacketStructure(const void* _pg_pkt, ECU_ThrottleSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + unsigned int _pg_tempbitfield = 0; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ThrottleCalibrationPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_ThrottleCalibrationMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Output position for 0% throttle in microseconds + // Range of pulseClosed is 0 to 65535. + _pg_user->pulseClosed = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Output position for 100% throttle in microseconds + // Range of pulseOpen is 0 to 65535. + _pg_user->pulseOpen = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Throttle configuration settings + if(decodeECU_ThrottleConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->config) == 0) + return 0; + + // Input PWM in microseconds for 0% throttle + // Range of pulseInputClosed is 0 to 4095. + _pg_tempbitfield = (_pg_data[_pg_byteindex] & 0xFF); + + _pg_tempbitfield <<= 4; + _pg_tempbitfield |= (_pg_data[_pg_byteindex + 1] >> 4); + + _pg_user->pulseInputClosed = _pg_tempbitfield; + + // Input PWM in microseconds for 100% throttle + // Range of pulseInputOpen is 0 to 4095. + _pg_tempbitfield = (_pg_data[_pg_byteindex + 1] & 0xF); + + _pg_tempbitfield <<= 8; + _pg_tempbitfield |= _pg_data[_pg_byteindex + 2]; + + _pg_user->pulseInputOpen = _pg_tempbitfield; + _pg_byteindex += 3; // close bit field + + return 1; + +}// decodeECU_ThrottleCalibrationPacketStructure + +/*! + * \brief Create the ECU_ThrottleCalibration packet + * + * The throttle calibration packet sets the calibration values for minimum and + * maximum throttle position. The ECU uses these values to interpolate the + * throttle command. + * \param _pg_pkt points to the packet which will be created by this function + * \param pulseClosed is Output position for 0% throttle in microseconds + * \param pulseOpen is Output position for 100% throttle in microseconds + * \param config is Throttle configuration settings + * \param pulseInputClosed is Input PWM in microseconds for 0% throttle + * \param pulseInputOpen is Input PWM in microseconds for 100% throttle + */ +void encodeECU_ThrottleCalibrationPacket(void* _pg_pkt, uint16_t pulseClosed, uint16_t pulseOpen, const ECU_ThrottleConfigBits_t* config, uint16_t pulseInputClosed, uint16_t pulseInputOpen) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned int _pg_tempbitfield = 0; + + // Output position for 0% throttle in microseconds + // Range of pulseClosed is 0 to 65535. + uint16ToBeBytes(pulseClosed, _pg_data, &_pg_byteindex); + + // Output position for 100% throttle in microseconds + // Range of pulseOpen is 0 to 65535. + uint16ToBeBytes(pulseOpen, _pg_data, &_pg_byteindex); + + // Throttle configuration settings + encodeECU_ThrottleConfigBits_t(_pg_data, &_pg_byteindex, config); + + // Input PWM in microseconds for 0% throttle + // Range of pulseInputClosed is 0 to 4095. + _pg_tempbitfield = (unsigned int)limitMax(pulseInputClosed, 4095); + _pg_data[_pg_byteindex + 1] = (uint8_t)(_pg_tempbitfield << 4); + + _pg_tempbitfield >>= 4; + _pg_data[_pg_byteindex] = (uint8_t)_pg_tempbitfield; + + // Input PWM in microseconds for 100% throttle + // Range of pulseInputOpen is 0 to 4095. + _pg_tempbitfield = (unsigned int)limitMax(pulseInputOpen, 4095); + _pg_data[_pg_byteindex + 2] = (uint8_t)_pg_tempbitfield; + + _pg_tempbitfield >>= 8; + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_tempbitfield; + _pg_byteindex += 3; // close bit field + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ThrottleCalibrationPacketID()); + +}// encodeECU_ThrottleCalibrationPacket + +/*! + * \brief Decode the ECU_ThrottleCalibration packet + * + * The throttle calibration packet sets the calibration values for minimum and + * maximum throttle position. The ECU uses these values to interpolate the + * throttle command. + * \param _pg_pkt points to the packet being decoded by this function + * \param pulseClosed receives Output position for 0% throttle in microseconds + * \param pulseOpen receives Output position for 100% throttle in microseconds + * \param config receives Throttle configuration settings + * \param pulseInputClosed receives Input PWM in microseconds for 0% throttle + * \param pulseInputOpen receives Input PWM in microseconds for 100% throttle + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ThrottleCalibrationPacket(const void* _pg_pkt, uint16_t* pulseClosed, uint16_t* pulseOpen, ECU_ThrottleConfigBits_t* config, uint16_t* pulseInputClosed, uint16_t* pulseInputOpen) +{ + unsigned int _pg_tempbitfield = 0; + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ThrottleCalibrationPacketID()) + return 0; + + if(_pg_numbytes < getECU_ThrottleCalibrationMinDataLength()) + return 0; + + // Output position for 0% throttle in microseconds + // Range of pulseClosed is 0 to 65535. + (*pulseClosed) = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Output position for 100% throttle in microseconds + // Range of pulseOpen is 0 to 65535. + (*pulseOpen) = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Throttle configuration settings + if(decodeECU_ThrottleConfigBits_t(_pg_data, &_pg_byteindex, config) == 0) + return 0; + + // Input PWM in microseconds for 0% throttle + // Range of pulseInputClosed is 0 to 4095. + _pg_tempbitfield = (_pg_data[_pg_byteindex] & 0xFF); + + _pg_tempbitfield <<= 4; + _pg_tempbitfield |= (_pg_data[_pg_byteindex + 1] >> 4); + + (*pulseInputClosed) = _pg_tempbitfield; + + // Input PWM in microseconds for 100% throttle + // Range of pulseInputOpen is 0 to 4095. + _pg_tempbitfield = (_pg_data[_pg_byteindex + 1] & 0xF); + + _pg_tempbitfield <<= 8; + _pg_tempbitfield |= _pg_data[_pg_byteindex + 2]; + + (*pulseInputOpen) = _pg_tempbitfield; + _pg_byteindex += 3; // close bit field + + return 1; + +}// decodeECU_ThrottleCalibrationPacket + +/*! + * \brief Create the ECU_RPMLoopCalibration packet + * + * The RPM loop calibration packet controls the operating parameters of the RPM + * governor on the ECU. The control loop is implemented using a closed-loop PID + * controller with user-configurable proportional, integral, and derivative + * gains, and a gain scaler. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_RPMLoopCalibrationPacketStructure(void* _pg_pkt, const ECU_GovernorSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Proportaional feedback gain from normalized RPM error to throttle fraction + // Range of pGain is 0.0f to 6.5535f. + float32ScaledTo2UnsignedBeBytes(_pg_user->pGain, _pg_data, &_pg_byteindex, 0.0f, 10000.0f); + + // Integral feedback gain from normalized RPM error to throttle fraction + // Range of iGain is 0.0f to 6.5535f. + float32ScaledTo2UnsignedBeBytes(_pg_user->iGain, _pg_data, &_pg_byteindex, 0.0f, 10000.0f); + + // Derivative feedback gain from normalized RPM error to throttle fraction + // Range of dGain is 0.0f to 6.5535f. + float32ScaledTo2UnsignedBeBytes(_pg_user->dGain, _pg_data, &_pg_byteindex, 0.0f, 10000.0f); + + // Gain scaler power, positive numbers increase gain with RPM, and vice versa. User 0 to disable gain scaling + // Range of scalePower is -2.54f to 2.54f. + float32ScaledTo1SignedBytes(_pg_user->scalePower, _pg_data, &_pg_byteindex, 50.0f); + + // Maximum commandable RPM + // Range of maxRPM is 0.0f to 25500.0f. + float32ScaledTo1UnsignedBytes(_pg_user->maxRPM, _pg_data, &_pg_byteindex, 0.0f, 0.01f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_RPMLoopCalibrationPacketID()); + +}// encodeECU_RPMLoopCalibrationPacketStructure + +/*! + * \brief Decode the ECU_RPMLoopCalibration packet + * + * The RPM loop calibration packet controls the operating parameters of the RPM + * governor on the ECU. The control loop is implemented using a closed-loop PID + * controller with user-configurable proportional, integral, and derivative + * gains, and a gain scaler. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_RPMLoopCalibrationPacketStructure(const void* _pg_pkt, ECU_GovernorSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_RPMLoopCalibrationPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_RPMLoopCalibrationMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Proportaional feedback gain from normalized RPM error to throttle fraction + // Range of pGain is 0.0f to 6.5535f. + _pg_user->pGain = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/10000.0f); + + // Integral feedback gain from normalized RPM error to throttle fraction + // Range of iGain is 0.0f to 6.5535f. + _pg_user->iGain = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/10000.0f); + + // Derivative feedback gain from normalized RPM error to throttle fraction + // Range of dGain is 0.0f to 6.5535f. + _pg_user->dGain = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/10000.0f); + + // Gain scaler power, positive numbers increase gain with RPM, and vice versa. User 0 to disable gain scaling + // Range of scalePower is -2.54f to 2.54f. + _pg_user->scalePower = float32ScaledFrom1SignedBytes(_pg_data, &_pg_byteindex, 1.0f/50.0f); + + // Maximum commandable RPM + // Range of maxRPM is 0.0f to 25500.0f. + _pg_user->maxRPM = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/0.01f); + + return 1; + +}// decodeECU_RPMLoopCalibrationPacketStructure + +/*! + * \brief Create the ECU_TPSDelayCalibration packet + * + * The throttle position delay configuration packet sends the desired throttle + * position delay (between 0 and 500ms) to the ECU, and also echoes back the + * TPS delay. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_TPSDelayCalibrationPacketStructure(void* _pg_pkt, const ECU_ThrottleSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Current TPS delay in seconds + // Range of delay is 0 to 255. + uint8ToBytes(_pg_user->delay, _pg_data, &_pg_byteindex); + + // Throttle delay configuration bits + encodeECU_ThrottleDelayConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->delayConfig); + + // Maximum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of maxDelay is 0 to 255. + uint8ToBytes(_pg_user->maxDelay, _pg_data, &_pg_byteindex); + + // Minimum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of minDelay is 0 to 255. + uint8ToBytes(_pg_user->minDelay, _pg_data, &_pg_byteindex); + + // throttle percentage below which the throttle position will gradually fall off rather than dropping instantaneously (Set this value to zero for the throttle to operate without a soft limit) + // Range of softLimit is 0 to 255. + uint8ToBytes(_pg_user->softLimit, _pg_data, &_pg_byteindex); + + // Throttle falloff rate. This determines the rate at which the throttle position decreases if it is below the soft limit + // Range of falloffRate is 0 to 255. + uint8ToBytes(_pg_user->falloffRate, _pg_data, &_pg_byteindex); + + // The throttle target position is the TPS input value, which may be given to the ECU via any of the available input types (analog, PWM, serial or CAN). This may vary from the output value, due to the dashpot functionality or the linearization curve. Note: this value cannot be written to the ECU + // Range of throttleTarget is 0 to 255. + uint8ToBytes(_pg_user->throttleTarget, _pg_data, &_pg_byteindex); + + // This value sets the minimum allowable throttle position in percent. The throttle position will not fall below this value + // Range of hardLimit is 0 to 255. + uint8ToBytes(_pg_user->hardLimit, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TPSDelayCalibrationPacketID()); + +}// encodeECU_TPSDelayCalibrationPacketStructure + +/*! + * \brief Decode the ECU_TPSDelayCalibration packet + * + * The throttle position delay configuration packet sends the desired throttle + * position delay (between 0 and 500ms) to the ECU, and also echoes back the + * TPS delay. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TPSDelayCalibrationPacketStructure(const void* _pg_pkt, ECU_ThrottleSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TPSDelayCalibrationPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_TPSDelayCalibrationMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Current TPS delay in seconds + // Range of delay is 0 to 255. + _pg_user->delay = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle delay configuration bits + if(decodeECU_ThrottleDelayConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->delayConfig) == 0) + return 0; + + // Maximum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of maxDelay is 0 to 255. + _pg_user->maxDelay = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Minimum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of minDelay is 0 to 255. + _pg_user->minDelay = uint8FromBytes(_pg_data, &_pg_byteindex); + + // throttle percentage below which the throttle position will gradually fall off rather than dropping instantaneously (Set this value to zero for the throttle to operate without a soft limit) + // Range of softLimit is 0 to 255. + _pg_user->softLimit = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle falloff rate. This determines the rate at which the throttle position decreases if it is below the soft limit + // Range of falloffRate is 0 to 255. + _pg_user->falloffRate = uint8FromBytes(_pg_data, &_pg_byteindex); + + // The throttle target position is the TPS input value, which may be given to the ECU via any of the available input types (analog, PWM, serial or CAN). This may vary from the output value, due to the dashpot functionality or the linearization curve. Note: this value cannot be written to the ECU + // Range of throttleTarget is 0 to 255. + _pg_user->throttleTarget = uint8FromBytes(_pg_data, &_pg_byteindex); + + // This value sets the minimum allowable throttle position in percent. The throttle position will not fall below this value + // Range of hardLimit is 0 to 255. + _pg_user->hardLimit = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_TPSDelayCalibrationPacketStructure + +/*! + * \brief Create the ECU_TPSDelayCalibration packet + * + * The throttle position delay configuration packet sends the desired throttle + * position delay (between 0 and 500ms) to the ECU, and also echoes back the + * TPS delay. + * \param _pg_pkt points to the packet which will be created by this function + * \param delay is Current TPS delay in seconds + * \param delayConfig is Throttle delay configuration bits + * \param maxDelay is Maximum TPS delay in seconds (for use with temperature dependent TPS delay setting + * \param minDelay is Minimum TPS delay in seconds (for use with temperature dependent TPS delay setting + * \param softLimit is throttle percentage below which the throttle position will gradually fall off rather than dropping instantaneously (Set this value to zero for the throttle to operate without a soft limit) + * \param falloffRate is Throttle falloff rate. This determines the rate at which the throttle position decreases if it is below the soft limit + * \param throttleTarget is The throttle target position is the TPS input value, which may be given to the ECU via any of the available input types (analog, PWM, serial or CAN). This may vary from the output value, due to the dashpot functionality or the linearization curve. Note: this value cannot be written to the ECU + * \param hardLimit is This value sets the minimum allowable throttle position in percent. The throttle position will not fall below this value + */ +void encodeECU_TPSDelayCalibrationPacket(void* _pg_pkt, uint8_t delay, const ECU_ThrottleDelayConfigBits_t* delayConfig, uint8_t maxDelay, uint8_t minDelay, uint8_t softLimit, uint8_t falloffRate, uint8_t throttleTarget, uint8_t hardLimit) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Current TPS delay in seconds + // Range of delay is 0 to 255. + uint8ToBytes(delay, _pg_data, &_pg_byteindex); + + // Throttle delay configuration bits + encodeECU_ThrottleDelayConfigBits_t(_pg_data, &_pg_byteindex, delayConfig); + + // Maximum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of maxDelay is 0 to 255. + uint8ToBytes(maxDelay, _pg_data, &_pg_byteindex); + + // Minimum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of minDelay is 0 to 255. + uint8ToBytes(minDelay, _pg_data, &_pg_byteindex); + + // throttle percentage below which the throttle position will gradually fall off rather than dropping instantaneously (Set this value to zero for the throttle to operate without a soft limit) + // Range of softLimit is 0 to 255. + uint8ToBytes(softLimit, _pg_data, &_pg_byteindex); + + // Throttle falloff rate. This determines the rate at which the throttle position decreases if it is below the soft limit + // Range of falloffRate is 0 to 255. + uint8ToBytes(falloffRate, _pg_data, &_pg_byteindex); + + // The throttle target position is the TPS input value, which may be given to the ECU via any of the available input types (analog, PWM, serial or CAN). This may vary from the output value, due to the dashpot functionality or the linearization curve. Note: this value cannot be written to the ECU + // Range of throttleTarget is 0 to 255. + uint8ToBytes(throttleTarget, _pg_data, &_pg_byteindex); + + // This value sets the minimum allowable throttle position in percent. The throttle position will not fall below this value + // Range of hardLimit is 0 to 255. + uint8ToBytes(hardLimit, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TPSDelayCalibrationPacketID()); + +}// encodeECU_TPSDelayCalibrationPacket + +/*! + * \brief Decode the ECU_TPSDelayCalibration packet + * + * The throttle position delay configuration packet sends the desired throttle + * position delay (between 0 and 500ms) to the ECU, and also echoes back the + * TPS delay. + * \param _pg_pkt points to the packet being decoded by this function + * \param delay receives Current TPS delay in seconds + * \param delayConfig receives Throttle delay configuration bits + * \param maxDelay receives Maximum TPS delay in seconds (for use with temperature dependent TPS delay setting + * \param minDelay receives Minimum TPS delay in seconds (for use with temperature dependent TPS delay setting + * \param softLimit receives throttle percentage below which the throttle position will gradually fall off rather than dropping instantaneously (Set this value to zero for the throttle to operate without a soft limit) + * \param falloffRate receives Throttle falloff rate. This determines the rate at which the throttle position decreases if it is below the soft limit + * \param throttleTarget receives The throttle target position is the TPS input value, which may be given to the ECU via any of the available input types (analog, PWM, serial or CAN). This may vary from the output value, due to the dashpot functionality or the linearization curve. Note: this value cannot be written to the ECU + * \param hardLimit receives This value sets the minimum allowable throttle position in percent. The throttle position will not fall below this value + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TPSDelayCalibrationPacket(const void* _pg_pkt, uint8_t* delay, ECU_ThrottleDelayConfigBits_t* delayConfig, uint8_t* maxDelay, uint8_t* minDelay, uint8_t* softLimit, uint8_t* falloffRate, uint8_t* throttleTarget, uint8_t* hardLimit) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TPSDelayCalibrationPacketID()) + return 0; + + if(_pg_numbytes < getECU_TPSDelayCalibrationMinDataLength()) + return 0; + + // Current TPS delay in seconds + // Range of delay is 0 to 255. + (*delay) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle delay configuration bits + if(decodeECU_ThrottleDelayConfigBits_t(_pg_data, &_pg_byteindex, delayConfig) == 0) + return 0; + + // Maximum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of maxDelay is 0 to 255. + (*maxDelay) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Minimum TPS delay in seconds (for use with temperature dependent TPS delay setting + // Range of minDelay is 0 to 255. + (*minDelay) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // throttle percentage below which the throttle position will gradually fall off rather than dropping instantaneously (Set this value to zero for the throttle to operate without a soft limit) + // Range of softLimit is 0 to 255. + (*softLimit) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle falloff rate. This determines the rate at which the throttle position decreases if it is below the soft limit + // Range of falloffRate is 0 to 255. + (*falloffRate) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // The throttle target position is the TPS input value, which may be given to the ECU via any of the available input types (analog, PWM, serial or CAN). This may vary from the output value, due to the dashpot functionality or the linearization curve. Note: this value cannot be written to the ECU + // Range of throttleTarget is 0 to 255. + (*throttleTarget) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // This value sets the minimum allowable throttle position in percent. The throttle position will not fall below this value + // Range of hardLimit is 0 to 255. + (*hardLimit) = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_TPSDelayCalibrationPacket + +/*! + * \brief Create the ECU_TelemetrySettings packet + * + * The telmetry settings packet is used to configure the telemetry data rates + * for the ECU. The ECU will echo the packet as confirmation of its receipt. + * Send a zero length packet to request the current settings. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_TelemetrySettingsPacketStructure(void* _pg_pkt, const ECU_TelemetrySettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Time between fast telemetry packets in 50ms increments + // Range of fastTelemetryPeriod is 0 to 255. + uint8ToBytes(_pg_user->fastTelemetryPeriod, _pg_data, &_pg_byteindex); + + // Time between slow telemetry packets in 500ms increments + // Range of slowTelemetryPeriod is 0 to 255. + uint8ToBytes(_pg_user->slowTelemetryPeriod, _pg_data, &_pg_byteindex); + + // Seconds of time the ECU waits after bootup before sending telemetry. + // Range of silencePeriod is 0 to 255. + uint8ToBytes(_pg_user->silencePeriod, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_TelemetrySettingsPacketID()); + +}// encodeECU_TelemetrySettingsPacketStructure + +/*! + * \brief Decode the ECU_TelemetrySettings packet + * + * The telmetry settings packet is used to configure the telemetry data rates + * for the ECU. The ECU will echo the packet as confirmation of its receipt. + * Send a zero length packet to request the current settings. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_TelemetrySettingsPacketStructure(const void* _pg_pkt, ECU_TelemetrySettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_TelemetrySettingsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_TelemetrySettingsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Time between fast telemetry packets in 50ms increments + // Range of fastTelemetryPeriod is 0 to 255. + _pg_user->fastTelemetryPeriod = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Time between slow telemetry packets in 500ms increments + // Range of slowTelemetryPeriod is 0 to 255. + _pg_user->slowTelemetryPeriod = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Seconds of time the ECU waits after bootup before sending telemetry. + // Range of silencePeriod is 0 to 255. + _pg_user->silencePeriod = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_TelemetrySettingsPacketStructure + +/*! + * \brief Create the ECU_PumpConfig packet + * + * The pump config packet is sent to the ECU to configure fuel pump control + * loop parameters. The ECU will echo the packet as confirmation of its + * receipt. Send a zero length packet to request the current settings. Note + * that the fuel pump configuration consists of two packets, this one and + * Pump2config. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_PumpConfigPacketStructure(void* _pg_pkt, const ECU_PumpSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Fuel pump proportional gain + // Range of kp is 0.0f to 655.35f. + float32ScaledTo2UnsignedBeBytes(_pg_user->kp, _pg_data, &_pg_byteindex, 0.0f, 100.0f); + + // Pump low pressure limit in kilo-Pascals + // Range of pressureLowerLimit is 0.0f to 4518.40871f. + float32ScaledTo2UnsignedBeBytes(_pg_user->pressureLowerLimit, _pg_data, &_pg_byteindex, 0.0f, 14.504f); + + // Pump high pressure limit in kilo-Pascals + // Range of pressureUpperLimit is 0.0f to 4518.40871f. + float32ScaledTo2UnsignedBeBytes(_pg_user->pressureUpperLimit, _pg_data, &_pg_byteindex, 0.0f, 14.504f); + + // Pump pressure setpoint in kilo-Pascals + // Range of pressureSetpoint is 0.0f to 4518.40871f. + float32ScaledTo2UnsignedBeBytes(_pg_user->pressureSetpoint, _pg_data, &_pg_byteindex, 0.0f, 14.504f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_PumpConfigPacketID()); + +}// encodeECU_PumpConfigPacketStructure + +/*! + * \brief Decode the ECU_PumpConfig packet + * + * The pump config packet is sent to the ECU to configure fuel pump control + * loop parameters. The ECU will echo the packet as confirmation of its + * receipt. Send a zero length packet to request the current settings. Note + * that the fuel pump configuration consists of two packets, this one and + * Pump2config. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_PumpConfigPacketStructure(const void* _pg_pkt, ECU_PumpSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_PumpConfigPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_PumpConfigMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Fuel pump proportional gain + // Range of kp is 0.0f to 655.35f. + _pg_user->kp = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/100.0f); + + // Pump low pressure limit in kilo-Pascals + // Range of pressureLowerLimit is 0.0f to 4518.40871f. + _pg_user->pressureLowerLimit = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/14.504f); + + // Pump high pressure limit in kilo-Pascals + // Range of pressureUpperLimit is 0.0f to 4518.40871f. + _pg_user->pressureUpperLimit = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/14.504f); + + // Pump pressure setpoint in kilo-Pascals + // Range of pressureSetpoint is 0.0f to 4518.40871f. + _pg_user->pressureSetpoint = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/14.504f); + + return 1; + +}// decodeECU_PumpConfigPacketStructure + +/*! + * \brief Create the ECU_Pump2Config packet + * + * The pump 2 config packet is used for further configuration of pump + * operation. This packet allows the user to configure integral gain values and + * PWM limits. The ECU will echo the packet as confirmation of its receipt. + * Send a zero length packet to request the current settings. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_Pump2ConfigPacketStructure(void* _pg_pkt, const ECU_PumpSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Fuel pump integral gain + // Range of ki is 0.0f to 65.535f. + float32ScaledTo2UnsignedBeBytes(_pg_user->ki, _pg_data, &_pg_byteindex, 0.0f, 1000.0f); + + // Minimum duty cycle in percent (250 = 100%) + // Range of minimumPWM is 0 to 255. + uint8ToBytes(_pg_user->minimumPWM, _pg_data, &_pg_byteindex); + + // Maximum duty cycle in percent (250 = 100%) + // Range of maximumPWM is 0 to 255. + uint8ToBytes(_pg_user->maximumPWM, _pg_data, &_pg_byteindex); + + // Reserved for future use + uint16ToBeBytes((uint16_t)(0), _pg_data, &_pg_byteindex); + + // Pump duty cycle ramp rate + // Range of rampRate is 0 to 255. + uint8ToBytes(_pg_user->rampRate, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_Pump2ConfigPacketID()); + +}// encodeECU_Pump2ConfigPacketStructure + +/*! + * \brief Decode the ECU_Pump2Config packet + * + * The pump 2 config packet is used for further configuration of pump + * operation. This packet allows the user to configure integral gain values and + * PWM limits. The ECU will echo the packet as confirmation of its receipt. + * Send a zero length packet to request the current settings. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_Pump2ConfigPacketStructure(const void* _pg_pkt, ECU_PumpSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_Pump2ConfigPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_Pump2ConfigMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Fuel pump integral gain + // Range of ki is 0.0f to 65.535f. + _pg_user->ki = float32ScaledFrom2UnsignedBeBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/1000.0f); + + // Minimum duty cycle in percent (250 = 100%) + // Range of minimumPWM is 0 to 255. + _pg_user->minimumPWM = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Maximum duty cycle in percent (250 = 100%) + // Range of maximumPWM is 0 to 255. + _pg_user->maximumPWM = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Reserved for future use + _pg_byteindex += 2; + + // Pump duty cycle ramp rate + // Range of rampRate is 0 to 255. + _pg_user->rampRate = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_Pump2ConfigPacketStructure + +/*! + * \brief Create the ECU_UserData packet + * + * The user data packet provides the user with 8 (eight) bytes of data for + * storing custom parameters or settings in ECU EEPROM (non-volatile) memory. + * The ECU does not make use of these values; they are simply for storing user + * data. Send a zero length packet to request the current settings. To set + * these values send the system command SET_USER_DATA. Data values must be set + * individually. + * \param _pg_pkt points to the packet which will be created by this function + * \param userData is 8 bytes of user data + */ +void encodeECU_UserDataPacket(void* _pg_pkt, const uint8_t userData[8]) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned _pg_i = 0; + + // 8 bytes of user data + // Range of userData is 0 to 255. + for(_pg_i = 0; _pg_i < 8; _pg_i++) + uint8ToBytes(userData[_pg_i], _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_UserDataPacketID()); + +}// encodeECU_UserDataPacket + +/*! + * \brief Decode the ECU_UserData packet + * + * The user data packet provides the user with 8 (eight) bytes of data for + * storing custom parameters or settings in ECU EEPROM (non-volatile) memory. + * The ECU does not make use of these values; they are simply for storing user + * data. Send a zero length packet to request the current settings. To set + * these values send the system command SET_USER_DATA. Data values must be set + * individually. + * \param _pg_pkt points to the packet being decoded by this function + * \param userData receives 8 bytes of user data + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_UserDataPacket(const void* _pg_pkt, uint8_t userData[8]) +{ + unsigned _pg_i = 0; + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_UserDataPacketID()) + return 0; + + if(_pg_numbytes < getECU_UserDataMinDataLength()) + return 0; + + // 8 bytes of user data + // Range of userData is 0 to 255. + for(_pg_i = 0; _pg_i < 8; _pg_i++) + userData[_pg_i] = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_UserDataPacket + +/*! + * \brief Create the ECU_ThrottleCurve packet + * + * First throttle curve packet, which contains the lower 6 term of the throttle + * linearization table. To request the throttle curve data (both packets), send + * the system command REQUEST_THROTTLE_CURVE_DATA. To change the throttle curve + * data send the system command SET_THROTTLE_CURVE_ELEMENT. + * \param _pg_pkt points to the packet which will be created by this function + * \param throttleCurve is Throttle output values for the lower 6 cells in the throttle lookup table + */ +void encodeECU_ThrottleCurvePacket(void* _pg_pkt, const float throttleCurve[6]) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned _pg_i = 0; + + // Throttle output values for the lower 6 cells in the throttle lookup table + // Range of throttleCurve is 0.0f to 127.5f. + for(_pg_i = 0; _pg_i < 6; _pg_i++) + float32ScaledTo1UnsignedBytes(throttleCurve[_pg_i], _pg_data, &_pg_byteindex, 0.0f, 2.0f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ThrottleCurvePacketID()); + +}// encodeECU_ThrottleCurvePacket + +/*! + * \brief Decode the ECU_ThrottleCurve packet + * + * First throttle curve packet, which contains the lower 6 term of the throttle + * linearization table. To request the throttle curve data (both packets), send + * the system command REQUEST_THROTTLE_CURVE_DATA. To change the throttle curve + * data send the system command SET_THROTTLE_CURVE_ELEMENT. + * \param _pg_pkt points to the packet being decoded by this function + * \param throttleCurve receives Throttle output values for the lower 6 cells in the throttle lookup table + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ThrottleCurvePacket(const void* _pg_pkt, float throttleCurve[6]) +{ + unsigned _pg_i = 0; + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ThrottleCurvePacketID()) + return 0; + + if(_pg_numbytes < getECU_ThrottleCurveMinDataLength()) + return 0; + + // Throttle output values for the lower 6 cells in the throttle lookup table + // Range of throttleCurve is 0.0f to 127.5f. + for(_pg_i = 0; _pg_i < 6; _pg_i++) + throttleCurve[_pg_i] = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/2.0f); + + return 1; + +}// decodeECU_ThrottleCurvePacket + +/*! + * \brief Create the ECU_ThrottleCurve1 packet + * + * Second throttle curve packet, which contains the upper 5 term of the + * throttle linearization table. To request the throttle curve data (both + * packets), send the system command REQUEST_THROTTLE_CURVE_DATA. To change the + * throttle curve data send the system command SET_THROTTLE_CURVE_ELEMENT. + * \param _pg_pkt points to the packet which will be created by this function + * \param throttleCurve is Throttle output values for the upper 5 cells in the throttle lookup table + */ +void encodeECU_ThrottleCurve1Packet(void* _pg_pkt, const float throttleCurve[5]) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned _pg_i = 0; + + // Throttle output values for the upper 5 cells in the throttle lookup table + // Range of throttleCurve is 0.0f to 127.5f. + for(_pg_i = 0; _pg_i < 5; _pg_i++) + float32ScaledTo1UnsignedBytes(throttleCurve[_pg_i], _pg_data, &_pg_byteindex, 0.0f, 2.0f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ThrottleCurve1PacketID()); + +}// encodeECU_ThrottleCurve1Packet + +/*! + * \brief Decode the ECU_ThrottleCurve1 packet + * + * Second throttle curve packet, which contains the upper 5 term of the + * throttle linearization table. To request the throttle curve data (both + * packets), send the system command REQUEST_THROTTLE_CURVE_DATA. To change the + * throttle curve data send the system command SET_THROTTLE_CURVE_ELEMENT. + * \param _pg_pkt points to the packet being decoded by this function + * \param throttleCurve receives Throttle output values for the upper 5 cells in the throttle lookup table + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ThrottleCurve1Packet(const void* _pg_pkt, float throttleCurve[5]) +{ + unsigned _pg_i = 0; + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ThrottleCurve1PacketID()) + return 0; + + if(_pg_numbytes < getECU_ThrottleCurve1MinDataLength()) + return 0; + + // Throttle output values for the upper 5 cells in the throttle lookup table + // Range of throttleCurve is 0.0f to 127.5f. + for(_pg_i = 0; _pg_i < 5; _pg_i++) + throttleCurve[_pg_i] = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/2.0f); + + return 1; + +}// decodeECU_ThrottleCurve1Packet + +/*! + * \brief Create the ECU_SystemCommand packet + * + * The system command packets follow the format provided below. Refer further + * in the document for complete documentation on each system command packet. + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_SystemCommandPacketStructure(void* _pg_pkt, const ECU_SystemCommand_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned _pg_i = 0; + + // The command enumeration + // Range of cmd is 0 to 255. + uint8ToBytes(_pg_user->cmd, _pg_data, &_pg_byteindex); + + // Up to 3 parameter bytes for a system command + // Range of parambytes is 0 to 255. + for(_pg_i = 0; _pg_i < 3; _pg_i++) + uint8ToBytes(_pg_user->parambytes[_pg_i], _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SystemCommandPacketID()); + +}// encodeECU_SystemCommandPacketStructure + +/*! + * \brief Decode the ECU_SystemCommand packet + * + * The system command packets follow the format provided below. Refer further + * in the document for complete documentation on each system command packet. + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SystemCommandPacketStructure(const void* _pg_pkt, ECU_SystemCommand_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + unsigned _pg_i = 0; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SystemCommandPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_SystemCommandMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // this packet has default fields, make sure they are set + for(_pg_i = 0; _pg_i < 3; _pg_i++) + _pg_user->parambytes[_pg_i] = 0; + + // The command enumeration + // Range of cmd is 0 to 255. + _pg_user->cmd = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + + if(_pg_byteindex + 1*3 > _pg_numbytes) + return 1; + + // Up to 3 parameter bytes for a system command + // Range of parambytes is 0 to 255. + for(_pg_i = 0; _pg_i < 3; _pg_i++) + _pg_user->parambytes[_pg_i] = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SystemCommandPacketStructure + +/*! + * \brief Create the ECU_CalibrateAnalogClosed packet + * + * Save the current value of the analog throttle position input as the 'Closed' + * position. To calibrate the closed analog input position, set the desired + * analog input level, and send this command to the ECU. + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_CalibrateAnalogClosedPacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_CALIBRATE_ANALOG_CLOSED), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_CalibrateAnalogClosedPacketID()); + +}// encodeECU_CalibrateAnalogClosedPacket + +/*! + * \brief Decode the ECU_CalibrateAnalogClosed packet + * + * Save the current value of the analog throttle position input as the 'Closed' + * position. To calibrate the closed analog input position, set the desired + * analog input level, and send this command to the ECU. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_CalibrateAnalogClosedPacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_CalibrateAnalogClosedPacketID()) + return 0; + + if(_pg_numbytes < getECU_CalibrateAnalogClosedMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_CALIBRATE_ANALOG_CLOSED + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_CALIBRATE_ANALOG_CLOSED) + return 0; + + return 1; + +}// decodeECU_CalibrateAnalogClosedPacket + +/*! + * \brief Create the ECU_CalibrateAnalogOpen packet + * + * Save the current value of the analog throttle position input as the 'Open' + * position. To calibrate the open analog input position, set the desired + * analog input level, and send this command to the ECU. + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_CalibrateAnalogOpenPacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_CALIBRATE_ANALOG_OPEN), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_CalibrateAnalogOpenPacketID()); + +}// encodeECU_CalibrateAnalogOpenPacket + +/*! + * \brief Decode the ECU_CalibrateAnalogOpen packet + * + * Save the current value of the analog throttle position input as the 'Open' + * position. To calibrate the open analog input position, set the desired + * analog input level, and send this command to the ECU. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_CalibrateAnalogOpenPacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_CalibrateAnalogOpenPacketID()) + return 0; + + if(_pg_numbytes < getECU_CalibrateAnalogOpenMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_CALIBRATE_ANALOG_OPEN + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_CALIBRATE_ANALOG_OPEN) + return 0; + + return 1; + +}// decodeECU_CalibrateAnalogOpenPacket + +/*! + * \brief Create the ECU_CalibratePulseClosed packet + * + * Save the current value of the throttle output pulse width to a temporary + * variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the + * ECU, this value will be saved as the 'Closed' pulse width. + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_CalibratePulseClosedPacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_CALIBRATE_PULSE_CLOSED), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_CalibratePulseClosedPacketID()); + +}// encodeECU_CalibratePulseClosedPacket + +/*! + * \brief Decode the ECU_CalibratePulseClosed packet + * + * Save the current value of the throttle output pulse width to a temporary + * variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the + * ECU, this value will be saved as the 'Closed' pulse width. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_CalibratePulseClosedPacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_CalibratePulseClosedPacketID()) + return 0; + + if(_pg_numbytes < getECU_CalibratePulseClosedMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_CALIBRATE_PULSE_CLOSED + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_CALIBRATE_PULSE_CLOSED) + return 0; + + return 1; + +}// decodeECU_CalibratePulseClosedPacket + +/*! + * \brief Create the ECU_CalibratePulseOpen packet + * + * Save the current value of the throttle output pulse width to a temporary + * variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the + * ECU, this value will be saved as the 'Open' pulse width. + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_CalibratePulseOpenPacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_CALIBRATE_PULSE_OPEN), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_CalibratePulseOpenPacketID()); + +}// encodeECU_CalibratePulseOpenPacket + +/*! + * \brief Decode the ECU_CalibratePulseOpen packet + * + * Save the current value of the throttle output pulse width to a temporary + * variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the + * ECU, this value will be saved as the 'Open' pulse width. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_CalibratePulseOpenPacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_CalibratePulseOpenPacketID()) + return 0; + + if(_pg_numbytes < getECU_CalibratePulseOpenMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_CALIBRATE_PULSE_OPEN + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_CALIBRATE_PULSE_OPEN) + return 0; + + return 1; + +}// decodeECU_CalibratePulseOpenPacket + +/*! + * \brief Create the ECU_CalibratePulseWrite packet + * + * Configure the throttle output positions. The CALIBRATE_PULSE_CLOSED and + * CALIBRATE_PULSE_OPEN commands should have already been sent to the ECU. The + * ECU then saves the temporary values as the 'Closed' and 'Open' throttle + * output values, respectively. + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_CalibratePulseWritePacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_CALIBRATE_PULSE_WRITE), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_CalibratePulseWritePacketID()); + +}// encodeECU_CalibratePulseWritePacket + +/*! + * \brief Decode the ECU_CalibratePulseWrite packet + * + * Configure the throttle output positions. The CALIBRATE_PULSE_CLOSED and + * CALIBRATE_PULSE_OPEN commands should have already been sent to the ECU. The + * ECU then saves the temporary values as the 'Closed' and 'Open' throttle + * output values, respectively. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_CalibratePulseWritePacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_CalibratePulseWritePacketID()) + return 0; + + if(_pg_numbytes < getECU_CalibratePulseWriteMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_CALIBRATE_PULSE_WRITE + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_CALIBRATE_PULSE_WRITE) + return 0; + + return 1; + +}// decodeECU_CalibratePulseWritePacket + +/*! + * \brief Create the ECU_SetOutputDriver packet + * + * Set one of four high-current output drivers. + * \param _pg_pkt points to the packet which will be created by this function + * \param driver is Select driver number (1, 2, 3 or 4) + * \param status is Set driver status (1 = ON, 0 = OFF) + */ +void encodeECU_SetOutputDriverPacket(void* _pg_pkt, uint8_t driver, uint8_t status) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_OUTPUT_DRIVER), _pg_data, &_pg_byteindex); + + // Select driver number (1, 2, 3 or 4) + // Range of driver is 0 to 255. + uint8ToBytes(driver, _pg_data, &_pg_byteindex); + + // Set driver status (1 = ON, 0 = OFF) + // Range of status is 0 to 255. + uint8ToBytes(status, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetOutputDriverPacketID()); + +}// encodeECU_SetOutputDriverPacket + +/*! + * \brief Decode the ECU_SetOutputDriver packet + * + * Set one of four high-current output drivers. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param driver receives Select driver number (1, 2, 3 or 4) + * \param status receives Set driver status (1 = ON, 0 = OFF) + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetOutputDriverPacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint8_t* driver, uint8_t* status) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetOutputDriverPacketID()) + return 0; + + if(_pg_numbytes < getECU_SetOutputDriverMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_OUTPUT_DRIVER + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_OUTPUT_DRIVER) + return 0; + + // Select driver number (1, 2, 3 or 4) + // Range of driver is 0 to 255. + (*driver) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Set driver status (1 = ON, 0 = OFF) + // Range of status is 0 to 255. + (*status) = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetOutputDriverPacket + +/*! + * \brief Create the ECU_SetThrottleCurveActive packet + * + * Turn the throttle linearization curve either on or off. + * \param _pg_pkt points to the packet which will be created by this function + * \param active is Curve active (1 = ON, 0 = OFF) + */ +void encodeECU_SetThrottleCurveActivePacket(void* _pg_pkt, uint8_t active) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_THROTTLE_CURVE_ACTIVE), _pg_data, &_pg_byteindex); + + // Curve active (1 = ON, 0 = OFF) + // Range of active is 0 to 255. + uint8ToBytes(active, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetThrottleCurveActivePacketID()); + +}// encodeECU_SetThrottleCurveActivePacket + +/*! + * \brief Decode the ECU_SetThrottleCurveActive packet + * + * Turn the throttle linearization curve either on or off. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param active receives Curve active (1 = ON, 0 = OFF) + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetThrottleCurveActivePacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint8_t* active) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetThrottleCurveActivePacketID()) + return 0; + + if(_pg_numbytes < getECU_SetThrottleCurveActiveMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_THROTTLE_CURVE_ACTIVE + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_THROTTLE_CURVE_ACTIVE) + return 0; + + // Curve active (1 = ON, 0 = OFF) + // Range of active is 0 to 255. + (*active) = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetThrottleCurveActivePacket + +/*! + * \brief Create the ECU_SetThrottleCurveElement packet + * + * Set individual elements in the throttle linearization lookup table. + * \param _pg_pkt points to the packet which will be created by this function + * \param index is Index into the throttle curve table from 0 to 10 (0% to 100%) throttle input + * \param throttleOutput is Percentage throttle output for this curve element + */ +void encodeECU_SetThrottleCurveElementPacket(void* _pg_pkt, uint8_t index, float throttleOutput) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_THROTTLE_CURVE_ELEMENT), _pg_data, &_pg_byteindex); + + // Index into the throttle curve table from 0 to 10 (0% to 100%) throttle input + // Range of index is 0 to 255. + uint8ToBytes(index, _pg_data, &_pg_byteindex); + + // Percentage throttle output for this curve element + // Range of throttleOutput is 0.0f to 127.5f. + float32ScaledTo1UnsignedBytes(throttleOutput, _pg_data, &_pg_byteindex, 0.0f, 2.0f); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetThrottleCurveElementPacketID()); + +}// encodeECU_SetThrottleCurveElementPacket + +/*! + * \brief Decode the ECU_SetThrottleCurveElement packet + * + * Set individual elements in the throttle linearization lookup table. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param index receives Index into the throttle curve table from 0 to 10 (0% to 100%) throttle input + * \param throttleOutput receives Percentage throttle output for this curve element + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetThrottleCurveElementPacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint8_t* index, float* throttleOutput) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetThrottleCurveElementPacketID()) + return 0; + + if(_pg_numbytes < getECU_SetThrottleCurveElementMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_THROTTLE_CURVE_ELEMENT + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_THROTTLE_CURVE_ELEMENT) + return 0; + + // Index into the throttle curve table from 0 to 10 (0% to 100%) throttle input + // Range of index is 0 to 255. + (*index) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Percentage throttle output for this curve element + // Range of throttleOutput is 0.0f to 127.5f. + (*throttleOutput) = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/2.0f); + + return 1; + +}// decodeECU_SetThrottleCurveElementPacket + +/*! + * \brief Create the ECU_RequestThrottleCurveData packet + * + * Request the throttle curve lookup table data. If requested on CAN, the data + * will be returned on CAN. If requested on RS232, the data will be returned on + * RS232. + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_RequestThrottleCurveDataPacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_REQUEST_THROTTLE_CURVE_DATA), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_RequestThrottleCurveDataPacketID()); + +}// encodeECU_RequestThrottleCurveDataPacket + +/*! + * \brief Decode the ECU_RequestThrottleCurveData packet + * + * Request the throttle curve lookup table data. If requested on CAN, the data + * will be returned on CAN. If requested on RS232, the data will be returned on + * RS232. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_RequestThrottleCurveDataPacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_RequestThrottleCurveDataPacketID()) + return 0; + + if(_pg_numbytes < getECU_RequestThrottleCurveDataMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_REQUEST_THROTTLE_CURVE_DATA + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_REQUEST_THROTTLE_CURVE_DATA) + return 0; + + return 1; + +}// decodeECU_RequestThrottleCurveDataPacket + +/*! + * \brief Create the ECU_ResetFuelUsed packet + * + * Reset the FuelUsed value. This will set the FuelUsed data to zero. + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_ResetFuelUsedPacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_RESET_FUEL_USED), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ResetFuelUsedPacketID()); + +}// encodeECU_ResetFuelUsedPacket + +/*! + * \brief Decode the ECU_ResetFuelUsed packet + * + * Reset the FuelUsed value. This will set the FuelUsed data to zero. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ResetFuelUsedPacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ResetFuelUsedPacketID()) + return 0; + + if(_pg_numbytes < getECU_ResetFuelUsedMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_RESET_FUEL_USED + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_RESET_FUEL_USED) + return 0; + + return 1; + +}// decodeECU_ResetFuelUsedPacket + +/*! + * \brief Create the ECU_SetFuelUsedDivisor packet + * + * Set the fuel used divisor + * \param _pg_pkt points to the packet which will be created by this function + * \param divisor is The fuel used divisor. The fuel used value is divided by this divisor before being transmitted by the auxiliary processor. Set this value to 1 to leave the fuel used data unaffected. If you use values greater than 100 the divisor is automatically interpreted as being in units of 0.01 (i.e. 100 times the resolution). + */ +void encodeECU_SetFuelUsedDivisorPacket(void* _pg_pkt, uint16_t divisor) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_FUEL_USED_DIVISOR), _pg_data, &_pg_byteindex); + + // The fuel used divisor. The fuel used value is divided by this divisor before being transmitted by the auxiliary processor. Set this value to 1 to leave the fuel used data unaffected. If you use values greater than 100 the divisor is automatically interpreted as being in units of 0.01 (i.e. 100 times the resolution). + // Range of divisor is 0 to 65535. + uint16ToBeBytes(divisor, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetFuelUsedDivisorPacketID()); + +}// encodeECU_SetFuelUsedDivisorPacket + +/*! + * \brief Decode the ECU_SetFuelUsedDivisor packet + * + * Set the fuel used divisor + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param divisor receives The fuel used divisor. The fuel used value is divided by this divisor before being transmitted by the auxiliary processor. Set this value to 1 to leave the fuel used data unaffected. If you use values greater than 100 the divisor is automatically interpreted as being in units of 0.01 (i.e. 100 times the resolution). + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetFuelUsedDivisorPacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint16_t* divisor) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetFuelUsedDivisorPacketID()) + return 0; + + if(_pg_numbytes < getECU_SetFuelUsedDivisorMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_FUEL_USED_DIVISOR + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_FUEL_USED_DIVISOR) + return 0; + + // The fuel used divisor. The fuel used value is divided by this divisor before being transmitted by the auxiliary processor. Set this value to 1 to leave the fuel used data unaffected. If you use values greater than 100 the divisor is automatically interpreted as being in units of 0.01 (i.e. 100 times the resolution). + // Range of divisor is 0 to 65535. + (*divisor) = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetFuelUsedDivisorPacket + +/*! + * \brief Create the ECU_SetFuelUsedResetFlag packet + * + * Set or clear the Fuel Used reset flag. If this flag is set, the FuelUsed + * data will reset (to zero) when the ECU is power cycled. + * \param _pg_pkt points to the packet which will be created by this function + * \param reset is 1 = Reset Fuel Used data on powerup 0 = Do not reset Fuel Used data on power up + */ +void encodeECU_SetFuelUsedResetFlagPacket(void* _pg_pkt, uint8_t reset) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_FUEL_USED_RESET_ON_STARTUP), _pg_data, &_pg_byteindex); + + // 1 = Reset Fuel Used data on powerup 0 = Do not reset Fuel Used data on power up + // Range of reset is 0 to 255. + uint8ToBytes(reset, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetFuelUsedResetFlagPacketID()); + +}// encodeECU_SetFuelUsedResetFlagPacket + +/*! + * \brief Decode the ECU_SetFuelUsedResetFlag packet + * + * Set or clear the Fuel Used reset flag. If this flag is set, the FuelUsed + * data will reset (to zero) when the ECU is power cycled. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param reset receives 1 = Reset Fuel Used data on powerup 0 = Do not reset Fuel Used data on power up + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetFuelUsedResetFlagPacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint8_t* reset) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetFuelUsedResetFlagPacketID()) + return 0; + + if(_pg_numbytes < getECU_SetFuelUsedResetFlagMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_FUEL_USED_RESET_ON_STARTUP + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_FUEL_USED_RESET_ON_STARTUP) + return 0; + + // 1 = Reset Fuel Used data on powerup 0 = Do not reset Fuel Used data on power up + // Range of reset is 0 to 255. + (*reset) = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetFuelUsedResetFlagPacket + +/*! + * \brief Create the ECU_SetGovernorMode packet + * + * Manually set the RPM governor mode. + * \param _pg_pkt points to the packet which will be created by this function + * \param mode is MODE 0 = Governor Off (Open loop throttle control) 1 = Governor based on throttle command 2 = Governor based on RPM command + */ +void encodeECU_SetGovernorModePacket(void* _pg_pkt, ECUGovernorMode mode) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_GOVERNOR_MODE), _pg_data, &_pg_byteindex); + + // MODE 0 = Governor Off (Open loop throttle control) 1 = Governor based on throttle command 2 = Governor based on RPM command + // Range of mode is 0 to 255. + uint8ToBytes(mode, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetGovernorModePacketID()); + +}// encodeECU_SetGovernorModePacket + +/*! + * \brief Decode the ECU_SetGovernorMode packet + * + * Manually set the RPM governor mode. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param mode receives MODE 0 = Governor Off (Open loop throttle control) 1 = Governor based on throttle command 2 = Governor based on RPM command + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetGovernorModePacket(const void* _pg_pkt, ECUSystemCommands* cmd, ECUGovernorMode* mode) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetGovernorModePacketID()) + return 0; + + if(_pg_numbytes < getECU_SetGovernorModeMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_GOVERNOR_MODE + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_GOVERNOR_MODE) + return 0; + + // MODE 0 = Governor Off (Open loop throttle control) 1 = Governor based on throttle command 2 = Governor based on RPM command + // Range of mode is 0 to 255. + (*mode) = (ECUGovernorMode)uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetGovernorModePacket + +/*! + * \brief Create the ECU_SetSerialMode packet + * + * Set the serial mode used for Autronic relay. When Autronic relay is enabled + * the external serial port of the ECU is reconfigured to connect to ECUCal, + * relaying bytes to the internal autronic processor; while still allowing the + * auxiliary processor to see telemetry from Autronic. This is fundamentally + * different from using the switch to calibration mode, which bypasses the + * auxiliary processor altogether, cutting it off from autronic telemetry. + * \param _pg_pkt points to the packet which will be created by this function + * \param mode is The serial relay mode to command + */ +void encodeECU_SetSerialModePacket(void* _pg_pkt, ECUAutronicRelayState mode) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_SERIAL_MODE), _pg_data, &_pg_byteindex); + + // The serial relay mode to command + // Range of mode is 0 to 255. + uint8ToBytes(mode, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetSerialModePacketID()); + +}// encodeECU_SetSerialModePacket + +/*! + * \brief Decode the ECU_SetSerialMode packet + * + * Set the serial mode used for Autronic relay. When Autronic relay is enabled + * the external serial port of the ECU is reconfigured to connect to ECUCal, + * relaying bytes to the internal autronic processor; while still allowing the + * auxiliary processor to see telemetry from Autronic. This is fundamentally + * different from using the switch to calibration mode, which bypasses the + * auxiliary processor altogether, cutting it off from autronic telemetry. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param mode receives The serial relay mode to command + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetSerialModePacket(const void* _pg_pkt, ECUSystemCommands* cmd, ECUAutronicRelayState* mode) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetSerialModePacketID()) + return 0; + + if(_pg_numbytes < getECU_SetSerialModeMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_SERIAL_MODE + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_SERIAL_MODE) + return 0; + + // The serial relay mode to command + // Range of mode is 0 to 255. + (*mode) = (ECUAutronicRelayState)uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetSerialModePacket + +/*! + * \brief Create the ECU_SetECUAddress packet + * + * Set a custom address value for the ECU. + * \param _pg_pkt points to the packet which will be created by this function + * \param address is ECU address in the range {1, 65534} + */ +void encodeECU_SetECUAddressPacket(void* _pg_pkt, uint16_t address) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_NODE_ID), _pg_data, &_pg_byteindex); + + // ECU address in the range {1, 65534} + // Range of address is 0 to 65535. + uint16ToBeBytes(address, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetECUAddressPacketID()); + +}// encodeECU_SetECUAddressPacket + +/*! + * \brief Decode the ECU_SetECUAddress packet + * + * Set a custom address value for the ECU. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param address receives ECU address in the range {1, 65534} + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetECUAddressPacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint16_t* address) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetECUAddressPacketID()) + return 0; + + if(_pg_numbytes < getECU_SetECUAddressMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_NODE_ID + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_NODE_ID) + return 0; + + // ECU address in the range {1, 65534} + // Range of address is 0 to 65535. + (*address) = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetECUAddressPacket + +/*! + * \brief Create the ECU_SetUserData packet + * + * Save a single byte of USER_DATA in EEPROM. + * \param _pg_pkt points to the packet which will be created by this function + * \param index is USER_DATA address (0 to 7) + * \param userdata is USER_DATA variable + */ +void encodeECU_SetUserDataPacket(void* _pg_pkt, uint8_t index, uint8_t userdata) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_SET_USER_DATA), _pg_data, &_pg_byteindex); + + // USER_DATA address (0 to 7) + // Range of index is 0 to 255. + uint8ToBytes(index, _pg_data, &_pg_byteindex); + + // USER_DATA variable + // Range of userdata is 0 to 255. + uint8ToBytes(userdata, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_SetUserDataPacketID()); + +}// encodeECU_SetUserDataPacket + +/*! + * \brief Decode the ECU_SetUserData packet + * + * Save a single byte of USER_DATA in EEPROM. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param index receives USER_DATA address (0 to 7) + * \param userdata receives USER_DATA variable + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_SetUserDataPacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint8_t* index, uint8_t* userdata) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_SetUserDataPacketID()) + return 0; + + if(_pg_numbytes < getECU_SetUserDataMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_SET_USER_DATA + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_SET_USER_DATA) + return 0; + + // USER_DATA address (0 to 7) + // Range of index is 0 to 255. + (*index) = uint8FromBytes(_pg_data, &_pg_byteindex); + + // USER_DATA variable + // Range of userdata is 0 to 255. + (*userdata) = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_SetUserDataPacket + +/*! + * \brief Create the ECU_ResetEngineTime packet + * + * Reset the engine runtime. + * \param _pg_pkt points to the packet which will be created by this function + * \param time is The new value of the engine time counter in seconds + */ +void encodeECU_ResetEngineTimePacket(void* _pg_pkt, uint32_t time) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_RESET_ENGINE_TIME), _pg_data, &_pg_byteindex); + + // The new value of the engine time counter in seconds + // Range of time is 0 to 16777215. + uint24ToBeBytes((uint32_t)(limitMax(time, 16777215)), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ResetEngineTimePacketID()); + +}// encodeECU_ResetEngineTimePacket + +/*! + * \brief Decode the ECU_ResetEngineTime packet + * + * Reset the engine runtime. + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \param time receives The new value of the engine time counter in seconds + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ResetEngineTimePacket(const void* _pg_pkt, ECUSystemCommands* cmd, uint32_t* time) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ResetEngineTimePacketID()) + return 0; + + if(_pg_numbytes < getECU_ResetEngineTimeMinDataLength()) + return 0; + + // this packet has default fields, make sure they are set + (*time) = 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_RESET_ENGINE_TIME + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_RESET_ENGINE_TIME) + return 0; + + if(_pg_byteindex + 3 > _pg_numbytes) + return 1; + + // The new value of the engine time counter in seconds + // Range of time is 0 to 16777215. + (*time) = (uint32_t)uint24FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_ResetEngineTimePacket + +/*! + * \brief Create the ECU_ResetECU packet + * + * Reset the ECU + * \param _pg_pkt points to the packet which will be created by this function + */ +void encodeECU_ResetECUPacket(void* _pg_pkt) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // The command enumeration + uint8ToBytes((uint8_t)(CMD_ECU_RESET_ECU), _pg_data, &_pg_byteindex); + + // Required constant value + uint8ToBytes((uint8_t)(0xA5), _pg_data, &_pg_byteindex); + + // Required constant value + uint8ToBytes((uint8_t)(0x5A), _pg_data, &_pg_byteindex); + + // Required constant value + uint8ToBytes((uint8_t)(0xCC), _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ResetECUPacketID()); + +}// encodeECU_ResetECUPacket + +/*! + * \brief Decode the ECU_ResetECU packet + * + * Reset the ECU + * \param _pg_pkt points to the packet being decoded by this function + * \param cmd receives The command enumeration + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ResetECUPacket(const void* _pg_pkt, ECUSystemCommands* cmd) +{ + int _pg_byteindex = 0; + const uint8_t* _pg_data = getECUPacketDataConst(_pg_pkt); + int _pg_numbytes = getECUPacketSize(_pg_pkt); + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ResetECUPacketID()) + return 0; + + if(_pg_numbytes < getECU_ResetECUMinDataLength()) + return 0; + + // The command enumeration + // Range of cmd is 0 to 255. + // Decoded value must be CMD_ECU_RESET_ECU + (*cmd) = (ECUSystemCommands)uint8FromBytes(_pg_data, &_pg_byteindex); + if ((*cmd) != CMD_ECU_RESET_ECU) + return 0; + + // Required constant value + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) 0xA5) + return 0; + + // Required constant value + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) 0x5A) + return 0; + + // Required constant value + if (uint8FromBytes(_pg_data, &_pg_byteindex) != (uint8_t) 0xCC) + return 0; + + return 1; + +}// decodeECU_ResetECUPacket +// end of ECUPackets.c diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUPackets.h b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUPackets.h new file mode 100644 index 0000000000..1bdf0e9c26 --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUPackets.h @@ -0,0 +1,1242 @@ +// ECUPackets.h was generated by ProtoGen version 3.2.a + +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Author: Oliver Walters / Currawong Engineering Pty Ltd + */ + + +#ifndef _ECUPACKETS_H +#define _ECUPACKETS_H + +// Language target is C, C++ compilers: don't mangle us +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + */ + +#include +#include "ECUProtocol.h" +#include "ECUDefines.h" +#include "ECUSettings.h" + +/*! + * The throttle command packet sets the throttle position setpoint. The ECU + * will adjust the throttle position based on this command. + */ +typedef struct +{ + float throttleCommand; //!< Commanded throttle position in percent +}ECU_ThrottleCommand_t; + +//! Create the ECU_ThrottleCommand packet from parameters +void encodeECU_ThrottleCommandPacket(void* pkt, float throttleCommand); + +//! Decode the ECU_ThrottleCommand packet to parameters +int decodeECU_ThrottleCommandPacket(const void* pkt, float* throttleCommand); + +//! return the packet ID for the ECU_ThrottleCommand packet +#define getECU_ThrottleCommandPacketID() (PKT_ECU_THROTTLE) + +//! return the minimum encoded length for the ECU_ThrottleCommand packet +#define getECU_ThrottleCommandMinDataLength() (2) + +//! return the maximum encoded length for the ECU_ThrottleCommand packet +#define getECU_ThrottleCommandMaxDataLength() (2) + +/*! + * The RPM command is used to send a target to the RPM governor on the ECU. + * Based on this command, the ECU will use a feedback loop to maintain the + * commanded engine speed by adjusting the throttle servo accordingly. If a + * valid RPM command is received by the ECU, it will automatically enter RPM + * control mode, and adjust the throttle position to match the desired RPM. + * Sending a throttle command will cause the ECU to stop the RPM loop and enter + * open-loop throttle control mode. + */ +typedef struct +{ + uint16_t rpmCmd; //!< Engine speed command in revolutions per minute + uint8_t rpmCmdHigh; //!< RPM command in units of 50 RPM + uint8_t rpmCmdLow; //!< Low part of RPM command from 0 to 49 +}ECU_RPMCommand_t; + +//! Create the ECU_RPMCommand packet +void encodeECU_RPMCommandPacketStructure(void* pkt, const ECU_RPMCommand_t* user); + +//! Decode the ECU_RPMCommand packet +int decodeECU_RPMCommandPacketStructure(const void* pkt, ECU_RPMCommand_t* user); + +//! return the packet ID for the ECU_RPMCommand packet +#define getECU_RPMCommandPacketID() (PKT_ECU_RPM_COMMAND) + +//! return the minimum encoded length for the ECU_RPMCommand packet +#define getECU_RPMCommandMinDataLength() (2) + +//! return the maximum encoded length for the ECU_RPMCommand packet +#define getECU_RPMCommandMaxDataLength() (2) + +typedef struct +{ + bool driverPin8; //!< 1 if driver 8 is on + bool driverPin7; //!< 1 if driver 7 is on + bool driverPin2; //!< 1 if driver 2 is on + bool driverPin1; //!< 1 if driver 1 is on + bool throttleCurveOn; //!< 1 if the throttle curve is on. + bool rs232mode; //!< 1 if autronic, else auxiliary. + bool errorIndicator; //!< 1 if any errors are set - refer to [error packet](#PKT_ECU_ERROR_MSG) + bool enabled; //!< Global enable based on physical input +}ECU_ecuStatusBits_t; + +/*! + * Fast telemetry contains high priority telemetry data and is transmitted at a + * user configurable period between 50ms (20Hz) and 10s. By default, the fast + * telemetry message is transmitted at 10Hz (every 100ms) + */ +typedef struct +{ + float throttle; //!< Throttle signal (0 to 100%) + uint16_t rpm; //!< Engine speed in revolutions per minute + uint32_t fuelUsed; //!< Fuel used in grams + ECU_ecuStatusBits_t ecuStatusBits; +}ECU_TelemetryFast_t; + +//! Encode a ECU_ecuStatusBits_t into a byte array +void encodeECU_ecuStatusBits_t(uint8_t* data, int* bytecount, const ECU_ecuStatusBits_t* user); + +//! Decode a ECU_ecuStatusBits_t from a byte array +int decodeECU_ecuStatusBits_t(const uint8_t* data, int* bytecount, ECU_ecuStatusBits_t* user); + +//! Create the ECU_TelemetryFast packet +void encodeECU_TelemetryFastPacketStructure(void* pkt, const ECU_TelemetryFast_t* user); + +//! Decode the ECU_TelemetryFast packet +int decodeECU_TelemetryFastPacketStructure(const void* pkt, ECU_TelemetryFast_t* user); + +//! Create the ECU_TelemetryFast packet from parameters +void encodeECU_TelemetryFastPacket(void* pkt, float throttle, uint16_t rpm, uint32_t fuelUsed, const ECU_ecuStatusBits_t* ecuStatusBits); + +//! Decode the ECU_TelemetryFast packet to parameters +int decodeECU_TelemetryFastPacket(const void* pkt, float* throttle, uint16_t* rpm, uint32_t* fuelUsed, ECU_ecuStatusBits_t* ecuStatusBits); + +//! return the packet ID for the ECU_TelemetryFast packet +#define getECU_TelemetryFastPacketID() (PKT_ECU_TELEMETRY_FAST) + +//! return the minimum encoded length for the ECU_TelemetryFast packet +#define getECU_TelemetryFastMinDataLength() (8) + +//! return the maximum encoded length for the ECU_TelemetryFast packet +#define getECU_TelemetryFastMaxDataLength() (8) + +/*! + * This is the first of three slower telemetry packets which are transmitted by + * the ECU at a user customizable period (between 0.5s and 10.0s). These three + * packets contain data that is not likely to change as quickly as the data in + * the fast telemetry packet. By default, the slow telemetry messages are + * transmitted at 1Hz (period of 1.0s). + */ +typedef struct +{ + uint16_t rpmCmd; //!< The reconstructed RPM command + float map; //!< The reconstructed manifold pressure in kilo-Pascals + ECUThrottleSource throttleSrc; //!< Source of the throttle information + uint16_t throttlePulse; //!< Throttle pulse width in microseconds + float cht; //!< Cylinder head temperature in Celsius + float baro; //!< Barometric pressure in kilo-Pascals +}ECU_TelemetrySlow0_t; + +//! Create the ECU_TelemetrySlow0 packet +void encodeECU_TelemetrySlow0PacketStructure(void* pkt, const ECU_TelemetrySlow0_t* user); + +//! Decode the ECU_TelemetrySlow0 packet +int decodeECU_TelemetrySlow0PacketStructure(const void* pkt, ECU_TelemetrySlow0_t* user); + +//! return the packet ID for the ECU_TelemetrySlow0 packet +#define getECU_TelemetrySlow0PacketID() (PKT_ECU_TELEMETRY_SLOW_0) + +//! return the minimum encoded length for the ECU_TelemetrySlow0 packet +#define getECU_TelemetrySlow0MinDataLength() (8) + +//! return the maximum encoded length for the ECU_TelemetrySlow0 packet +#define getECU_TelemetrySlow0MaxDataLength() (8) + +/*! + * ECU RPM governor mode enumeration + */ +typedef enum +{ + ECU_GOV_MODE_NONE, //!< RPM governor is off + ECU_GOV_MODE_THROTTLE,//!< RPM governer setpoint is based on throttle input + ECU_GOV_MODE_DIRECT //!< RPM governor setpoint comes from direct command +} ECUGovernorMode; + +/*! + * The second of three slow telemetry packets + */ +typedef struct +{ + float mat; //!< Inlet air temperature in Celsius + float fuelPressure; //!< Fuel pressure in kilo-Pascals + uint32_t hobbs; //!< Engine run time in seconds. + float voltage; //!< Input voltage in Volts + ECUGovernorMode governorMode; //!< Operational mode of the governor +}ECU_TelemetrySlow1_t; + +//! Create the ECU_TelemetrySlow1 packet +void encodeECU_TelemetrySlow1PacketStructure(void* pkt, const ECU_TelemetrySlow1_t* user); + +//! Decode the ECU_TelemetrySlow1 packet +int decodeECU_TelemetrySlow1PacketStructure(const void* pkt, ECU_TelemetrySlow1_t* user); + +//! return the packet ID for the ECU_TelemetrySlow1 packet +#define getECU_TelemetrySlow1PacketID() (PKT_ECU_TELEMETRY_SLOW_1) + +//! return the minimum encoded length for the ECU_TelemetrySlow1 packet +#define getECU_TelemetrySlow1MinDataLength() (8) + +//! return the maximum encoded length for the ECU_TelemetrySlow1 packet +#define getECU_TelemetrySlow1MaxDataLength() (8) + +/*! + * The third of three slow telemetry packets + */ +typedef struct +{ + float cpuLoad; //!< CPU load in percent + float chargeTemp; //!< Charge temperature in Celsius + float injectorDuty; //!< Injector duty cycle in percent + float ignAngle1; //!< First ignition advance angle in degrees + float ignAngle2; //!< Second ignition advance angle in degrees + float flowRate; //!< Fuel flow rate in grams per minute +}ECU_TelemetrySlow2_t; + +//! Create the ECU_TelemetrySlow2 packet +void encodeECU_TelemetrySlow2PacketStructure(void* pkt, const ECU_TelemetrySlow2_t* user); + +//! Decode the ECU_TelemetrySlow2 packet +int decodeECU_TelemetrySlow2PacketStructure(const void* pkt, ECU_TelemetrySlow2_t* user); + +//! return the packet ID for the ECU_TelemetrySlow2 packet +#define getECU_TelemetrySlow2PacketID() (PKT_ECU_TELEMETRY_SLOW_2) + +//! return the minimum encoded length for the ECU_TelemetrySlow2 packet +#define getECU_TelemetrySlow2MinDataLength() (8) + +//! return the maximum encoded length for the ECU_TelemetrySlow2 packet +#define getECU_TelemetrySlow2MaxDataLength() (8) + +/*! + * Enumeration of auxiliary to autronic serial relay states. Autronic relay is + * an advanced feature used to allow simultaneous connection of the Autronic + * ECUCal software and the auxiliary processor. Autronic relay should only be + * needed for engine development. + */ +typedef enum +{ + AUT_RELAY_OFF, //!< Relay is disengaged, 19200 autronic interface rate; must use calibration switch to connect to Autronic + AUT_RELAY_PENDING,//!< Relay enabled but not detected, 19200 autronic and external serial interface rate + AUT_RELAY_ON //!< Relay detected, 38400 autronic and external serial interface rate +} ECUAutronicRelayState; + +/*! + * The hardware config packet contains the ECU serial number and various ECU + * configuration data. Send a zero length packet to request this data. + */ +typedef struct +{ + uint16_t serialNumber; //!< ECU serial number + uint16_t fuelDivisor; //!< Fuel used divisior. If the divisor is greater than 100 then it is interpreted as units of 0.01 (for a higher resolution fuel calibration) + ECUAutronicRelayState relayState; //!< Autronic relay state. This is a volatile status which will reset to AUT_RELAY_OFF on ECU power cycle. + bool resetFuelUsedOnStart; //!< Set if the fuel used value is reset each on each ECU power cycle +}ECU_HardwareConfig_t; + +//! Create the ECU_HardwareConfig packet +void encodeECU_HardwareConfigPacketStructure(void* pkt, const ECU_HardwareConfig_t* user); + +//! Decode the ECU_HardwareConfig packet +int decodeECU_HardwareConfigPacketStructure(const void* pkt, ECU_HardwareConfig_t* user); + +//! return the packet ID for the ECU_HardwareConfig packet +#define getECU_HardwareConfigPacketID() (PKT_ECU_HARDWARE_CONFIG) + +//! return the minimum encoded length for the ECU_HardwareConfig packet +#define getECU_HardwareConfigMinDataLength() (5) + +//! return the maximum encoded length for the ECU_HardwareConfig packet +#define getECU_HardwareConfigMaxDataLength() (5) + +/*! + * The software version packet contains the auxiliary processor firmware + * version information. Send a zero length packet to request this data. + */ +typedef struct +{ + bool release; //!< 1 = Release version, 0 = Testing version + unsigned versionMajor : 6; //!< Major version number + uint8_t versionMinor; //!< Minor version number + uint8_t versionRev; //!< Revision number + uint8_t month; //!< The release month from 1 (January) to 12 (December) + uint8_t day; //!< The release day of month from 1 to 31 + uint16_t year; //!< The release year + uint16_t checksum; //!< Firmware checksum +}ECU_Version_t; + +//! Create the ECU_Version packet +void encodeECU_VersionPacketStructure(void* pkt, const ECU_Version_t* user); + +//! Decode the ECU_Version packet +int decodeECU_VersionPacketStructure(const void* pkt, ECU_Version_t* user); + +//! return the packet ID for the ECU_Version packet +#define getECU_VersionPacketID() (PKT_ECU_SOFTWARE_VERSION) + +//! return the minimum encoded length for the ECU_Version packet +#define getECU_VersionMinDataLength() (8) + +//! return the maximum encoded length for the ECU_Version packet +#define getECU_VersionMaxDataLength() (8) + +/*! + * The errors packet contains error status information for the ECU. If any + * error bits are set, then the global error bit in the [fast + * telemetry](#PKT_ECU_TELEMETRY_FAST) packet will also be set. Send a zero + * length packet to request this data. + */ +typedef struct +{ + ECU_AutronicErrorBits_t autronicErrors; //!< Error bits for the Autronic processor + ECU_AuxiliaryErrorBits_t auxiliaryErrors; //!< Error bits for the auxiliary processor +}ECU_Errors_t; + +//! Create the ECU_Errors packet +void encodeECU_ErrorsPacketStructure(void* pkt, const ECU_Errors_t* user); + +//! Decode the ECU_Errors packet +int decodeECU_ErrorsPacketStructure(const void* pkt, ECU_Errors_t* user); + +//! return the packet ID for the ECU_Errors packet +#define getECU_ErrorsPacketID() (PKT_ECU_ERROR_MSG) + +//! return the minimum encoded length for the ECU_Errors packet +#define getECU_ErrorsMinDataLength() (8) + +//! return the maximum encoded length for the ECU_Errors packet +#define getECU_ErrorsMaxDataLength() (8) + +/*! + * The power cycles packet contains information on the reset condition of the + * ECU. Send a zero length packet to request this data. + */ +typedef struct +{ + uint16_t powerCycles; //!< Number of power cycles + uint8_t reserved; + uint8_t resetCode; //!< Auxiliary processor reset code + uint32_t systemTime; //!< Milliseconds since system reset +}ECU_PowerCycles_t; + +//! Create the ECU_PowerCycles packet +void encodeECU_PowerCyclesPacketStructure(void* pkt, const ECU_PowerCycles_t* user); + +//! Decode the ECU_PowerCycles packet +int decodeECU_PowerCyclesPacketStructure(const void* pkt, ECU_PowerCycles_t* user); + +//! return the packet ID for the ECU_PowerCycles packet +#define getECU_PowerCyclesPacketID() (PKT_ECU_POWER_CYCLES) + +//! return the minimum encoded length for the ECU_PowerCycles packet +#define getECU_PowerCyclesMinDataLength() (8) + +//! return the maximum encoded length for the ECU_PowerCycles packet +#define getECU_PowerCyclesMaxDataLength() (8) + +/*! + * The fuel pump debug packet contains information on the pump control system. + * Send a zero length packet to request this data. + */ +typedef struct +{ + float pTerm; //!< Proportional term of the pump feedback control in percent + float iTerm; //!< Integral term of the pump feedback control in percent + float dutyCycle; //!< Pump duty cycle in percent + float fuelPressure; //!< Fuel pressure in kilo-Pascals +}ECU_PumpDebug_t; + +//! Create the ECU_PumpDebug packet +void encodeECU_PumpDebugPacketStructure(void* pkt, const ECU_PumpDebug_t* user); + +//! Decode the ECU_PumpDebug packet +int decodeECU_PumpDebugPacketStructure(const void* pkt, ECU_PumpDebug_t* user); + +//! return the packet ID for the ECU_PumpDebug packet +#define getECU_PumpDebugPacketID() (PKT_ECU_PUMP_DEBUG) + +//! return the minimum encoded length for the ECU_PumpDebug packet +#define getECU_PumpDebugMinDataLength() (8) + +//! return the maximum encoded length for the ECU_PumpDebug packet +#define getECU_PumpDebugMaxDataLength() (8) + +/*! + * While the engine time contained in the ECU telemetry packet can be reset by + * the user, the ECU also stores the total engine time, which cannot be reset + * by the user. Send a zero length packet to request this data. + */ +typedef struct +{ + uint32_t hobbs; //!< Total engine run time in seconds +}ECU_TotalEngineTime_t; + +//! Create the ECU_TotalEngineTime packet from parameters +void encodeECU_TotalEngineTimePacket(void* pkt, uint32_t hobbs); + +//! Decode the ECU_TotalEngineTime packet to parameters +int decodeECU_TotalEngineTimePacket(const void* pkt, uint32_t* hobbs); + +//! return the packet ID for the ECU_TotalEngineTime packet +#define getECU_TotalEngineTimePacketID() (PKT_ECU_TOTAL_ENGINE_TIME) + +//! return the minimum encoded length for the ECU_TotalEngineTime packet +#define getECU_TotalEngineTimeMinDataLength() (3) + +//! return the maximum encoded length for the ECU_TotalEngineTime packet +#define getECU_TotalEngineTimeMaxDataLength() (3) + +/*! + * The eeprom settings packet contains information on the non-volatile ECU + * settings stored in eeprom. In particular, it provides a checksum of the + * settings data for easy comparison of settings between different ECUs. Send a + * zero length packet to request this data. + */ +typedef struct +{ + uint8_t eepromVersion; //!< Version of the EEPROM data + uint16_t eepromSize; //!< Number of bytes of the EEPROM data + uint16_t eepromChecksum; //!< Fletcher's checksum of the EEPROM data + ECU_CompileOptions_t compileOptions; //!< ECU compilation options +}ECU_eepromSettings_t; + +//! Create the ECU_eepromSettings packet +void encodeECU_eepromSettingsPacketStructure(void* pkt, const ECU_eepromSettings_t* user); + +//! Decode the ECU_eepromSettings packet +int decodeECU_eepromSettingsPacketStructure(const void* pkt, ECU_eepromSettings_t* user); + +//! Create the ECU_eepromSettings packet from parameters +void encodeECU_eepromSettingsPacket(void* pkt, uint8_t eepromVersion, uint16_t eepromSize, uint16_t eepromChecksum, const ECU_CompileOptions_t* compileOptions); + +//! Decode the ECU_eepromSettings packet to parameters +int decodeECU_eepromSettingsPacket(const void* pkt, uint8_t* eepromVersion, uint16_t* eepromSize, uint16_t* eepromChecksum, ECU_CompileOptions_t* compileOptions); + +//! return the packet ID for the ECU_eepromSettings packet +#define getECU_eepromSettingsPacketID() (PKT_ECU_SETTINGS_DATA) + +//! return the minimum encoded length for the ECU_eepromSettings packet +#define getECU_eepromSettingsMinDataLength() (7) + +//! return the maximum encoded length for the ECU_eepromSettings packet +#define getECU_eepromSettingsMaxDataLength() (7) + +/*! + * Control loop settings for the CHT control loop + */ +typedef struct +{ + uint8_t dTermFilter; //!< Filter value for derivative term + bool enabled; //!< CHT control loop enabled + uint8_t targetTemp; //!< Target CHT temperature + float Kp; //!< Proportaional gain Kp + float Ki; //!< Proportaional gain Ki + float Kd; //!< Proportaional gain Kd +}ECU_CHTLoopSettings_t; + +//! Create the ECU_CHTLoopSettings packet +void encodeECU_CHTLoopSettingsPacketStructure(void* pkt, const ECU_CHTLoopSettings_t* user); + +//! Decode the ECU_CHTLoopSettings packet +int decodeECU_CHTLoopSettingsPacketStructure(const void* pkt, ECU_CHTLoopSettings_t* user); + +//! Create the ECU_CHTLoopSettings packet from parameters +void encodeECU_CHTLoopSettingsPacket(void* pkt, uint8_t dTermFilter, bool enabled, uint8_t targetTemp, float Kp, float Ki, float Kd); + +//! Decode the ECU_CHTLoopSettings packet to parameters +int decodeECU_CHTLoopSettingsPacket(const void* pkt, uint8_t* dTermFilter, bool* enabled, uint8_t* targetTemp, float* Kp, float* Ki, float* Kd); + +//! return the packet ID for the ECU_CHTLoopSettings packet +#define getECU_CHTLoopSettingsPacketID() (PKT_ECU_CHT_LOOP) + +//! return the minimum encoded length for the ECU_CHTLoopSettings packet +#define getECU_CHTLoopSettingsMinDataLength() (8) + +//! return the maximum encoded length for the ECU_CHTLoopSettings packet +#define getECU_CHTLoopSettingsMaxDataLength() (8) + +/*! + * Dual pump control telemetry. Send a zero-length packet with this identifier + * to the ECU to poll (request) this packet. + */ +typedef struct +{ + uint8_t mode; //!< Current pump mode (which pump is running). Refer to the DualFuelPumpMode enumeration. + uint8_t state; //!< Current pump state machine state. Refer to the DualFuelPumpState enumeration. + uint16_t stateTimer; //!< Time spent in current state +}ECU_DualPumpControlTelemetry_t; + +//! Create the ECU_DualPumpControlTelemetry packet +void encodeECU_DualPumpControlTelemetryPacketStructure(void* pkt, const ECU_DualPumpControlTelemetry_t* user); + +//! Decode the ECU_DualPumpControlTelemetry packet +int decodeECU_DualPumpControlTelemetryPacketStructure(const void* pkt, ECU_DualPumpControlTelemetry_t* user); + +//! return the packet ID for the ECU_DualPumpControlTelemetry packet +#define getECU_DualPumpControlTelemetryPacketID() (0x08) + +//! return the minimum encoded length for the ECU_DualPumpControlTelemetry packet +#define getECU_DualPumpControlTelemetryMinDataLength() (4) + +//! return the maximum encoded length for the ECU_DualPumpControlTelemetry packet +#define getECU_DualPumpControlTelemetryMaxDataLength() (4) + +/*! + * Set the telemetry period for dual-pump messages + */ +typedef struct +{ + uint8_t period; //!< Telemetry period (0 = Off) +}ECU_DualPump_SetTelemetryPeriod_t; + +//! Create the ECU_DualPump_SetTelemetryPeriod packet from parameters +void encodeECU_DualPump_SetTelemetryPeriodPacket(void* pkt, uint8_t period); + +//! Decode the ECU_DualPump_SetTelemetryPeriod packet to parameters +int decodeECU_DualPump_SetTelemetryPeriodPacket(const void* pkt, uint8_t* period); + +//! return the packet ID for the ECU_DualPump_SetTelemetryPeriod packet +#define getECU_DualPump_SetTelemetryPeriodPacketID() (0x08) + +//! return the minimum encoded length for the ECU_DualPump_SetTelemetryPeriod packet +#define getECU_DualPump_SetTelemetryPeriodMinDataLength() (2) + +//! return the maximum encoded length for the ECU_DualPump_SetTelemetryPeriod packet +#define getECU_DualPump_SetTelemetryPeriodMaxDataLength() (2) + +/*! + * Command to manually select a given pump mode. + */ +typedef struct +{ + uint8_t pump; //!< Pump selection (see DualFuelPumpMode enumeration) +}ECU_DualPump_SelectPump_t; + +//! Create the ECU_DualPump_SelectPump packet from parameters +void encodeECU_DualPump_SelectPumpPacket(void* pkt, uint8_t pump); + +//! Decode the ECU_DualPump_SelectPump packet to parameters +int decodeECU_DualPump_SelectPumpPacket(const void* pkt, uint8_t* pump); + +//! return the packet ID for the ECU_DualPump_SelectPump packet +#define getECU_DualPump_SelectPumpPacketID() (0x08) + +//! return the minimum encoded length for the ECU_DualPump_SelectPump packet +#define getECU_DualPump_SelectPumpMinDataLength() (3) + +//! return the maximum encoded length for the ECU_DualPump_SelectPump packet +#define getECU_DualPump_SelectPumpMaxDataLength() (3) + +/*! + * Command to temporarily run a particular pump in test mode. ECU will revert + * to OTHER pump when test expires + */ +typedef struct +{ + uint8_t pump; //!< Pump selection (see DualFuelPumpMode enumeration) + uint8_t timeout; //!< Test timeout +}ECU_DualPump_TestPump_t; + +//! Create the ECU_DualPump_TestPump packet +void encodeECU_DualPump_TestPumpPacketStructure(void* pkt, const ECU_DualPump_TestPump_t* user); + +//! Decode the ECU_DualPump_TestPump packet +int decodeECU_DualPump_TestPumpPacketStructure(const void* pkt, ECU_DualPump_TestPump_t* user); + +//! return the packet ID for the ECU_DualPump_TestPump packet +#define getECU_DualPump_TestPumpPacketID() (0x08) + +//! return the minimum encoded length for the ECU_DualPump_TestPump packet +#define getECU_DualPump_TestPumpMinDataLength() (3) + +//! return the maximum encoded length for the ECU_DualPump_TestPump packet +#define getECU_DualPump_TestPumpMaxDataLength() (4) + +//! Create the ECU_ThrottleCalibration packet +void encodeECU_ThrottleCalibrationPacketStructure(void* pkt, const ECU_ThrottleSettings_t* user); + +//! Decode the ECU_ThrottleCalibration packet +int decodeECU_ThrottleCalibrationPacketStructure(const void* pkt, ECU_ThrottleSettings_t* user); + +//! Create the ECU_ThrottleCalibration packet from parameters +void encodeECU_ThrottleCalibrationPacket(void* pkt, uint16_t pulseClosed, uint16_t pulseOpen, const ECU_ThrottleConfigBits_t* config, uint16_t pulseInputClosed, uint16_t pulseInputOpen); + +//! Decode the ECU_ThrottleCalibration packet to parameters +int decodeECU_ThrottleCalibrationPacket(const void* pkt, uint16_t* pulseClosed, uint16_t* pulseOpen, ECU_ThrottleConfigBits_t* config, uint16_t* pulseInputClosed, uint16_t* pulseInputOpen); + +//! return the packet ID for the ECU_ThrottleCalibration packet +#define getECU_ThrottleCalibrationPacketID() (PKT_ECU_THROTTLE_CALIBRATION) + +//! return the minimum encoded length for the ECU_ThrottleCalibration packet +#define getECU_ThrottleCalibrationMinDataLength() (8) + +//! return the maximum encoded length for the ECU_ThrottleCalibration packet +#define getECU_ThrottleCalibrationMaxDataLength() (8) + +//! Create the ECU_RPMLoopCalibration packet +void encodeECU_RPMLoopCalibrationPacketStructure(void* pkt, const ECU_GovernorSettings_t* user); + +//! Decode the ECU_RPMLoopCalibration packet +int decodeECU_RPMLoopCalibrationPacketStructure(const void* pkt, ECU_GovernorSettings_t* user); + +//! return the packet ID for the ECU_RPMLoopCalibration packet +#define getECU_RPMLoopCalibrationPacketID() (PKT_ECU_RPM_CALIBRATION) + +//! return the minimum encoded length for the ECU_RPMLoopCalibration packet +#define getECU_RPMLoopCalibrationMinDataLength() (8) + +//! return the maximum encoded length for the ECU_RPMLoopCalibration packet +#define getECU_RPMLoopCalibrationMaxDataLength() (8) + +//! Create the ECU_TPSDelayCalibration packet +void encodeECU_TPSDelayCalibrationPacketStructure(void* pkt, const ECU_ThrottleSettings_t* user); + +//! Decode the ECU_TPSDelayCalibration packet +int decodeECU_TPSDelayCalibrationPacketStructure(const void* pkt, ECU_ThrottleSettings_t* user); + +//! Create the ECU_TPSDelayCalibration packet from parameters +void encodeECU_TPSDelayCalibrationPacket(void* pkt, uint8_t delay, const ECU_ThrottleDelayConfigBits_t* delayConfig, uint8_t maxDelay, uint8_t minDelay, uint8_t softLimit, uint8_t falloffRate, uint8_t throttleTarget, uint8_t hardLimit); + +//! Decode the ECU_TPSDelayCalibration packet to parameters +int decodeECU_TPSDelayCalibrationPacket(const void* pkt, uint8_t* delay, ECU_ThrottleDelayConfigBits_t* delayConfig, uint8_t* maxDelay, uint8_t* minDelay, uint8_t* softLimit, uint8_t* falloffRate, uint8_t* throttleTarget, uint8_t* hardLimit); + +//! return the packet ID for the ECU_TPSDelayCalibration packet +#define getECU_TPSDelayCalibrationPacketID() (PKT_ECU_TPS_DELAY_CONFIG) + +//! return the minimum encoded length for the ECU_TPSDelayCalibration packet +#define getECU_TPSDelayCalibrationMinDataLength() (8) + +//! return the maximum encoded length for the ECU_TPSDelayCalibration packet +#define getECU_TPSDelayCalibrationMaxDataLength() (8) + +/*! + * The telmetry settings packet is used to configure the telemetry data rates + * for the ECU. The ECU will echo the packet as confirmation of its receipt. + * Send a zero length packet to request the current settings. + */ +typedef struct +{ + uint8_t fastTelemetryPeriod; //!< Time between fast telemetry packets in 50ms increments + uint8_t slowTelemetryPeriod; //!< Time between slow telemetry packets in 500ms increments + uint8_t silencePeriod; //!< Seconds of time the ECU waits after bootup before sending telemetry. +}ECU_TelemetrySettings_t; + +//! Create the ECU_TelemetrySettings packet +void encodeECU_TelemetrySettingsPacketStructure(void* pkt, const ECU_TelemetrySettings_t* user); + +//! Decode the ECU_TelemetrySettings packet +int decodeECU_TelemetrySettingsPacketStructure(const void* pkt, ECU_TelemetrySettings_t* user); + +//! return the packet ID for the ECU_TelemetrySettings packet +#define getECU_TelemetrySettingsPacketID() (PKT_ECU_TELEMETRY_SETTINGS) + +//! return the minimum encoded length for the ECU_TelemetrySettings packet +#define getECU_TelemetrySettingsMinDataLength() (3) + +//! return the maximum encoded length for the ECU_TelemetrySettings packet +#define getECU_TelemetrySettingsMaxDataLength() (3) + +//! Create the ECU_PumpConfig packet +void encodeECU_PumpConfigPacketStructure(void* pkt, const ECU_PumpSettings_t* user); + +//! Decode the ECU_PumpConfig packet +int decodeECU_PumpConfigPacketStructure(const void* pkt, ECU_PumpSettings_t* user); + +//! return the packet ID for the ECU_PumpConfig packet +#define getECU_PumpConfigPacketID() (PKT_ECU_PUMP_CONFIG) + +//! return the minimum encoded length for the ECU_PumpConfig packet +#define getECU_PumpConfigMinDataLength() (8) + +//! return the maximum encoded length for the ECU_PumpConfig packet +#define getECU_PumpConfigMaxDataLength() (8) + +//! Create the ECU_Pump2Config packet +void encodeECU_Pump2ConfigPacketStructure(void* pkt, const ECU_PumpSettings_t* user); + +//! Decode the ECU_Pump2Config packet +int decodeECU_Pump2ConfigPacketStructure(const void* pkt, ECU_PumpSettings_t* user); + +//! return the packet ID for the ECU_Pump2Config packet +#define getECU_Pump2ConfigPacketID() (PKT_ECU_PUMP_2_CONFIG) + +//! return the minimum encoded length for the ECU_Pump2Config packet +#define getECU_Pump2ConfigMinDataLength() (7) + +//! return the maximum encoded length for the ECU_Pump2Config packet +#define getECU_Pump2ConfigMaxDataLength() (7) + +/*! + * The user data packet provides the user with 8 (eight) bytes of data for + * storing custom parameters or settings in ECU EEPROM (non-volatile) memory. + * The ECU does not make use of these values; they are simply for storing user + * data. Send a zero length packet to request the current settings. To set + * these values send the system command SET_USER_DATA. Data values must be set + * individually. + */ +typedef struct +{ + uint8_t userData[8]; //!< 8 bytes of user data +}ECU_UserData_t; + +//! Create the ECU_UserData packet from parameters +void encodeECU_UserDataPacket(void* pkt, const uint8_t userData[8]); + +//! Decode the ECU_UserData packet to parameters +int decodeECU_UserDataPacket(const void* pkt, uint8_t userData[8]); + +//! return the packet ID for the ECU_UserData packet +#define getECU_UserDataPacketID() (PKT_ECU_USER_DATA) + +//! return the minimum encoded length for the ECU_UserData packet +#define getECU_UserDataMinDataLength() (8) + +//! return the maximum encoded length for the ECU_UserData packet +#define getECU_UserDataMaxDataLength() (8) + +/*! + * First throttle curve packet, which contains the lower 6 term of the throttle + * linearization table. To request the throttle curve data (both packets), send + * the system command REQUEST_THROTTLE_CURVE_DATA. To change the throttle curve + * data send the system command SET_THROTTLE_CURVE_ELEMENT. + */ +typedef struct +{ + float throttleCurve[6]; //!< Throttle output values for the lower 6 cells in the throttle lookup table +}ECU_ThrottleCurve_t; + +//! Create the ECU_ThrottleCurve packet from parameters +void encodeECU_ThrottleCurvePacket(void* pkt, const float throttleCurve[6]); + +//! Decode the ECU_ThrottleCurve packet to parameters +int decodeECU_ThrottleCurvePacket(const void* pkt, float throttleCurve[6]); + +//! return the packet ID for the ECU_ThrottleCurve packet +#define getECU_ThrottleCurvePacketID() (PKT_ECU_THROTTLE_CURVE_0) + +//! return the minimum encoded length for the ECU_ThrottleCurve packet +#define getECU_ThrottleCurveMinDataLength() (6) + +//! return the maximum encoded length for the ECU_ThrottleCurve packet +#define getECU_ThrottleCurveMaxDataLength() (6) + +//! Create the ECU_ThrottleCurve1 packet from parameters +void encodeECU_ThrottleCurve1Packet(void* pkt, const float throttleCurve[5]); + +//! Decode the ECU_ThrottleCurve1 packet to parameters +int decodeECU_ThrottleCurve1Packet(const void* pkt, float throttleCurve[5]); + +//! return the packet ID for the ECU_ThrottleCurve1 packet +#define getECU_ThrottleCurve1PacketID() (PKT_ECU_THROTTLE_CURVE_1) + +//! return the minimum encoded length for the ECU_ThrottleCurve1 packet +#define getECU_ThrottleCurve1MinDataLength() (5) + +//! return the maximum encoded length for the ECU_ThrottleCurve1 packet +#define getECU_ThrottleCurve1MaxDataLength() (5) + +/*! + * The system command packets follow the format provided below. Refer further + * in the document for complete documentation on each system command packet. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration + uint8_t parambytes[3]; //!< Up to 3 parameter bytes for a system command +}ECU_SystemCommand_t; + +//! Create the ECU_SystemCommand packet +void encodeECU_SystemCommandPacketStructure(void* pkt, const ECU_SystemCommand_t* user); + +//! Decode the ECU_SystemCommand packet +int decodeECU_SystemCommandPacketStructure(const void* pkt, ECU_SystemCommand_t* user); + +//! return the packet ID for the ECU_SystemCommand packet +#define getECU_SystemCommandPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SystemCommand packet +#define getECU_SystemCommandMinDataLength() (1) + +//! return the maximum encoded length for the ECU_SystemCommand packet +#define getECU_SystemCommandMaxDataLength() (4) + +/*! + * Save the current value of the analog throttle position input as the 'Closed' + * position. To calibrate the closed analog input position, set the desired + * analog input level, and send this command to the ECU. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_CalibrateAnalogClosed_t; + +//! Create the ECU_CalibrateAnalogClosed packet from parameters +void encodeECU_CalibrateAnalogClosedPacket(void* pkt); + +//! Decode the ECU_CalibrateAnalogClosed packet to parameters +int decodeECU_CalibrateAnalogClosedPacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_CalibrateAnalogClosed packet +#define getECU_CalibrateAnalogClosedPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_CalibrateAnalogClosed packet +#define getECU_CalibrateAnalogClosedMinDataLength() (1) + +//! return the maximum encoded length for the ECU_CalibrateAnalogClosed packet +#define getECU_CalibrateAnalogClosedMaxDataLength() (1) + +/*! + * Save the current value of the analog throttle position input as the 'Open' + * position. To calibrate the open analog input position, set the desired + * analog input level, and send this command to the ECU. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_CalibrateAnalogOpen_t; + +//! Create the ECU_CalibrateAnalogOpen packet from parameters +void encodeECU_CalibrateAnalogOpenPacket(void* pkt); + +//! Decode the ECU_CalibrateAnalogOpen packet to parameters +int decodeECU_CalibrateAnalogOpenPacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_CalibrateAnalogOpen packet +#define getECU_CalibrateAnalogOpenPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_CalibrateAnalogOpen packet +#define getECU_CalibrateAnalogOpenMinDataLength() (1) + +//! return the maximum encoded length for the ECU_CalibrateAnalogOpen packet +#define getECU_CalibrateAnalogOpenMaxDataLength() (1) + +/*! + * Save the current value of the throttle output pulse width to a temporary + * variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the + * ECU, this value will be saved as the 'Closed' pulse width. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_CalibratePulseClosed_t; + +//! Create the ECU_CalibratePulseClosed packet from parameters +void encodeECU_CalibratePulseClosedPacket(void* pkt); + +//! Decode the ECU_CalibratePulseClosed packet to parameters +int decodeECU_CalibratePulseClosedPacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_CalibratePulseClosed packet +#define getECU_CalibratePulseClosedPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_CalibratePulseClosed packet +#define getECU_CalibratePulseClosedMinDataLength() (1) + +//! return the maximum encoded length for the ECU_CalibratePulseClosed packet +#define getECU_CalibratePulseClosedMaxDataLength() (1) + +/*! + * Save the current value of the throttle output pulse width to a temporary + * variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the + * ECU, this value will be saved as the 'Open' pulse width. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_CalibratePulseOpen_t; + +//! Create the ECU_CalibratePulseOpen packet from parameters +void encodeECU_CalibratePulseOpenPacket(void* pkt); + +//! Decode the ECU_CalibratePulseOpen packet to parameters +int decodeECU_CalibratePulseOpenPacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_CalibratePulseOpen packet +#define getECU_CalibratePulseOpenPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_CalibratePulseOpen packet +#define getECU_CalibratePulseOpenMinDataLength() (1) + +//! return the maximum encoded length for the ECU_CalibratePulseOpen packet +#define getECU_CalibratePulseOpenMaxDataLength() (1) + +/*! + * Configure the throttle output positions. The CALIBRATE_PULSE_CLOSED and + * CALIBRATE_PULSE_OPEN commands should have already been sent to the ECU. The + * ECU then saves the temporary values as the 'Closed' and 'Open' throttle + * output values, respectively. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_CalibratePulseWrite_t; + +//! Create the ECU_CalibratePulseWrite packet from parameters +void encodeECU_CalibratePulseWritePacket(void* pkt); + +//! Decode the ECU_CalibratePulseWrite packet to parameters +int decodeECU_CalibratePulseWritePacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_CalibratePulseWrite packet +#define getECU_CalibratePulseWritePacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_CalibratePulseWrite packet +#define getECU_CalibratePulseWriteMinDataLength() (1) + +//! return the maximum encoded length for the ECU_CalibratePulseWrite packet +#define getECU_CalibratePulseWriteMaxDataLength() (1) + +/*! + * Set one of four high-current output drivers. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint8_t driver; //!< Select driver number (1, 2, 3 or 4) + uint8_t status; //!< Set driver status (1 = ON, 0 = OFF) +}ECU_SetOutputDriver_t; + +//! Create the ECU_SetOutputDriver packet from parameters +void encodeECU_SetOutputDriverPacket(void* pkt, uint8_t driver, uint8_t status); + +//! Decode the ECU_SetOutputDriver packet to parameters +int decodeECU_SetOutputDriverPacket(const void* pkt, ECUSystemCommands* cmd, uint8_t* driver, uint8_t* status); + +//! return the packet ID for the ECU_SetOutputDriver packet +#define getECU_SetOutputDriverPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetOutputDriver packet +#define getECU_SetOutputDriverMinDataLength() (3) + +//! return the maximum encoded length for the ECU_SetOutputDriver packet +#define getECU_SetOutputDriverMaxDataLength() (3) + +/*! + * Turn the throttle linearization curve either on or off. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint8_t active; //!< Curve active (1 = ON, 0 = OFF) +}ECU_SetThrottleCurveActive_t; + +//! Create the ECU_SetThrottleCurveActive packet from parameters +void encodeECU_SetThrottleCurveActivePacket(void* pkt, uint8_t active); + +//! Decode the ECU_SetThrottleCurveActive packet to parameters +int decodeECU_SetThrottleCurveActivePacket(const void* pkt, ECUSystemCommands* cmd, uint8_t* active); + +//! return the packet ID for the ECU_SetThrottleCurveActive packet +#define getECU_SetThrottleCurveActivePacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetThrottleCurveActive packet +#define getECU_SetThrottleCurveActiveMinDataLength() (2) + +//! return the maximum encoded length for the ECU_SetThrottleCurveActive packet +#define getECU_SetThrottleCurveActiveMaxDataLength() (2) + +/*! + * Set individual elements in the throttle linearization lookup table. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint8_t index; //!< Index into the throttle curve table from 0 to 10 (0% to 100%) throttle input + float throttleOutput; //!< Percentage throttle output for this curve element +}ECU_SetThrottleCurveElement_t; + +//! Create the ECU_SetThrottleCurveElement packet from parameters +void encodeECU_SetThrottleCurveElementPacket(void* pkt, uint8_t index, float throttleOutput); + +//! Decode the ECU_SetThrottleCurveElement packet to parameters +int decodeECU_SetThrottleCurveElementPacket(const void* pkt, ECUSystemCommands* cmd, uint8_t* index, float* throttleOutput); + +//! return the packet ID for the ECU_SetThrottleCurveElement packet +#define getECU_SetThrottleCurveElementPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetThrottleCurveElement packet +#define getECU_SetThrottleCurveElementMinDataLength() (3) + +//! return the maximum encoded length for the ECU_SetThrottleCurveElement packet +#define getECU_SetThrottleCurveElementMaxDataLength() (3) + +/*! + * Request the throttle curve lookup table data. If requested on CAN, the data + * will be returned on CAN. If requested on RS232, the data will be returned on + * RS232. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_RequestThrottleCurveData_t; + +//! Create the ECU_RequestThrottleCurveData packet from parameters +void encodeECU_RequestThrottleCurveDataPacket(void* pkt); + +//! Decode the ECU_RequestThrottleCurveData packet to parameters +int decodeECU_RequestThrottleCurveDataPacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_RequestThrottleCurveData packet +#define getECU_RequestThrottleCurveDataPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_RequestThrottleCurveData packet +#define getECU_RequestThrottleCurveDataMinDataLength() (1) + +//! return the maximum encoded length for the ECU_RequestThrottleCurveData packet +#define getECU_RequestThrottleCurveDataMaxDataLength() (1) + +/*! + * Reset the FuelUsed value. This will set the FuelUsed data to zero. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_ResetFuelUsed_t; + +//! Create the ECU_ResetFuelUsed packet from parameters +void encodeECU_ResetFuelUsedPacket(void* pkt); + +//! Decode the ECU_ResetFuelUsed packet to parameters +int decodeECU_ResetFuelUsedPacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_ResetFuelUsed packet +#define getECU_ResetFuelUsedPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_ResetFuelUsed packet +#define getECU_ResetFuelUsedMinDataLength() (1) + +//! return the maximum encoded length for the ECU_ResetFuelUsed packet +#define getECU_ResetFuelUsedMaxDataLength() (1) + +/*! + * Set the fuel used divisor + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint16_t divisor; //!< The fuel used divisor. The fuel used value is divided by this divisor before being transmitted by the auxiliary processor. Set this value to 1 to leave the fuel used data unaffected. If you use values greater than 100 the divisor is automatically interpreted as being in units of 0.01 (i.e. 100 times the resolution). +}ECU_SetFuelUsedDivisor_t; + +//! Create the ECU_SetFuelUsedDivisor packet from parameters +void encodeECU_SetFuelUsedDivisorPacket(void* pkt, uint16_t divisor); + +//! Decode the ECU_SetFuelUsedDivisor packet to parameters +int decodeECU_SetFuelUsedDivisorPacket(const void* pkt, ECUSystemCommands* cmd, uint16_t* divisor); + +//! return the packet ID for the ECU_SetFuelUsedDivisor packet +#define getECU_SetFuelUsedDivisorPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetFuelUsedDivisor packet +#define getECU_SetFuelUsedDivisorMinDataLength() (3) + +//! return the maximum encoded length for the ECU_SetFuelUsedDivisor packet +#define getECU_SetFuelUsedDivisorMaxDataLength() (3) + +/*! + * Set or clear the Fuel Used reset flag. If this flag is set, the FuelUsed + * data will reset (to zero) when the ECU is power cycled. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint8_t reset; //!< 1 = Reset Fuel Used data on powerup 0 = Do not reset Fuel Used data on power up +}ECU_SetFuelUsedResetFlag_t; + +//! Create the ECU_SetFuelUsedResetFlag packet from parameters +void encodeECU_SetFuelUsedResetFlagPacket(void* pkt, uint8_t reset); + +//! Decode the ECU_SetFuelUsedResetFlag packet to parameters +int decodeECU_SetFuelUsedResetFlagPacket(const void* pkt, ECUSystemCommands* cmd, uint8_t* reset); + +//! return the packet ID for the ECU_SetFuelUsedResetFlag packet +#define getECU_SetFuelUsedResetFlagPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetFuelUsedResetFlag packet +#define getECU_SetFuelUsedResetFlagMinDataLength() (2) + +//! return the maximum encoded length for the ECU_SetFuelUsedResetFlag packet +#define getECU_SetFuelUsedResetFlagMaxDataLength() (2) + +/*! + * Manually set the RPM governor mode. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + ECUGovernorMode mode; //!< MODE 0 = Governor Off (Open loop throttle control) 1 = Governor based on throttle command 2 = Governor based on RPM command +}ECU_SetGovernorMode_t; + +//! Create the ECU_SetGovernorMode packet from parameters +void encodeECU_SetGovernorModePacket(void* pkt, ECUGovernorMode mode); + +//! Decode the ECU_SetGovernorMode packet to parameters +int decodeECU_SetGovernorModePacket(const void* pkt, ECUSystemCommands* cmd, ECUGovernorMode* mode); + +//! return the packet ID for the ECU_SetGovernorMode packet +#define getECU_SetGovernorModePacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetGovernorMode packet +#define getECU_SetGovernorModeMinDataLength() (2) + +//! return the maximum encoded length for the ECU_SetGovernorMode packet +#define getECU_SetGovernorModeMaxDataLength() (2) + +/*! + * Set the serial mode used for Autronic relay. When Autronic relay is enabled + * the external serial port of the ECU is reconfigured to connect to ECUCal, + * relaying bytes to the internal autronic processor; while still allowing the + * auxiliary processor to see telemetry from Autronic. This is fundamentally + * different from using the switch to calibration mode, which bypasses the + * auxiliary processor altogether, cutting it off from autronic telemetry. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + ECUAutronicRelayState mode; //!< The serial relay mode to command +}ECU_SetSerialMode_t; + +//! Create the ECU_SetSerialMode packet from parameters +void encodeECU_SetSerialModePacket(void* pkt, ECUAutronicRelayState mode); + +//! Decode the ECU_SetSerialMode packet to parameters +int decodeECU_SetSerialModePacket(const void* pkt, ECUSystemCommands* cmd, ECUAutronicRelayState* mode); + +//! return the packet ID for the ECU_SetSerialMode packet +#define getECU_SetSerialModePacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetSerialMode packet +#define getECU_SetSerialModeMinDataLength() (2) + +//! return the maximum encoded length for the ECU_SetSerialMode packet +#define getECU_SetSerialModeMaxDataLength() (2) + +/*! + * Set a custom address value for the ECU. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint16_t address; //!< ECU address in the range {1, 65534} +}ECU_SetECUAddress_t; + +//! Create the ECU_SetECUAddress packet from parameters +void encodeECU_SetECUAddressPacket(void* pkt, uint16_t address); + +//! Decode the ECU_SetECUAddress packet to parameters +int decodeECU_SetECUAddressPacket(const void* pkt, ECUSystemCommands* cmd, uint16_t* address); + +//! return the packet ID for the ECU_SetECUAddress packet +#define getECU_SetECUAddressPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetECUAddress packet +#define getECU_SetECUAddressMinDataLength() (3) + +//! return the maximum encoded length for the ECU_SetECUAddress packet +#define getECU_SetECUAddressMaxDataLength() (3) + +/*! + * Save a single byte of USER_DATA in EEPROM. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint8_t index; //!< USER_DATA address (0 to 7) + uint8_t userdata; //!< USER_DATA variable +}ECU_SetUserData_t; + +//! Create the ECU_SetUserData packet from parameters +void encodeECU_SetUserDataPacket(void* pkt, uint8_t index, uint8_t userdata); + +//! Decode the ECU_SetUserData packet to parameters +int decodeECU_SetUserDataPacket(const void* pkt, ECUSystemCommands* cmd, uint8_t* index, uint8_t* userdata); + +//! return the packet ID for the ECU_SetUserData packet +#define getECU_SetUserDataPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_SetUserData packet +#define getECU_SetUserDataMinDataLength() (3) + +//! return the maximum encoded length for the ECU_SetUserData packet +#define getECU_SetUserDataMaxDataLength() (3) + +/*! + * Reset the engine runtime. + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. + uint32_t time; //!< The new value of the engine time counter in seconds +}ECU_ResetEngineTime_t; + +//! Create the ECU_ResetEngineTime packet from parameters +void encodeECU_ResetEngineTimePacket(void* pkt, uint32_t time); + +//! Decode the ECU_ResetEngineTime packet to parameters +int decodeECU_ResetEngineTimePacket(const void* pkt, ECUSystemCommands* cmd, uint32_t* time); + +//! return the packet ID for the ECU_ResetEngineTime packet +#define getECU_ResetEngineTimePacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_ResetEngineTime packet +#define getECU_ResetEngineTimeMinDataLength() (1) + +//! return the maximum encoded length for the ECU_ResetEngineTime packet +#define getECU_ResetEngineTimeMaxDataLength() (4) + +/*! + * Reset the ECU + */ +typedef struct +{ + ECUSystemCommands cmd; //!< The command enumeration. Field is encoded constant. +}ECU_ResetECU_t; + +//! Create the ECU_ResetECU packet from parameters +void encodeECU_ResetECUPacket(void* pkt); + +//! Decode the ECU_ResetECU packet to parameters +int decodeECU_ResetECUPacket(const void* pkt, ECUSystemCommands* cmd); + +//! return the packet ID for the ECU_ResetECU packet +#define getECU_ResetECUPacketID() (PKT_ECU_SYS_CMD) + +//! return the minimum encoded length for the ECU_ResetECU packet +#define getECU_ResetECUMinDataLength() (4) + +//! return the maximum encoded length for the ECU_ResetECU packet +#define getECU_ResetECUMaxDataLength() (4) + +#ifdef __cplusplus +} +#endif +#endif // _ECUPACKETS_H diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUProtocol.c b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUProtocol.c new file mode 100644 index 0000000000..f2cd1cd96d --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUProtocol.c @@ -0,0 +1,148 @@ +// ECUProtocol.c was generated by ProtoGen version 3.2.a + +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Author: Oliver Walters / Currawong Engineering Pty Ltd + */ + + +#include "ECUProtocol.h" + +/*! + * \brief Lookup label for 'ECUPackets' enum entry + * + * \param value is the integer value of the enum entry + * \return string label of the given entry + */ +const char* ECUPackets_EnumLabel(int value) +{ + switch (value) + { + default: + return ""; + case PKT_ECU_TELEMETRY_FAST: + return translateECU("PKT_ECU_TELEMETRY_FAST"); + case PKT_ECU_TELEMETRY_SLOW_0: + return translateECU("PKT_ECU_TELEMETRY_SLOW_0"); + case PKT_ECU_TELEMETRY_SLOW_1: + return translateECU("PKT_ECU_TELEMETRY_SLOW_1"); + case PKT_ECU_TELEMETRY_SLOW_2: + return translateECU("PKT_ECU_TELEMETRY_SLOW_2"); + case PKT_ECU_TELEMETRY_SLOW_3: + return translateECU("PKT_ECU_TELEMETRY_SLOW_3"); + case PKT_ECU_THROTTLE_CALIBRATION: + return translateECU("PKT_ECU_THROTTLE_CALIBRATION"); + case PKT_ECU_THROTTLE: + return translateECU("PKT_ECU_THROTTLE"); + case PKT_ECU_RPM_COMMAND: + return translateECU("PKT_ECU_RPM_COMMAND"); + case PKT_ECU_RPM_CALIBRATION: + return translateECU("PKT_ECU_RPM_CALIBRATION"); + case PKT_ECU_HARDWARE_CONFIG: + return translateECU("PKT_ECU_HARDWARE_CONFIG"); + case PKT_ECU_SOFTWARE_VERSION: + return translateECU("PKT_ECU_SOFTWARE_VERSION"); + case PKT_ECU_TPS_DELAY_CONFIG: + return translateECU("PKT_ECU_TPS_DELAY_CONFIG"); + case PKT_ECU_TELEMETRY_SETTINGS: + return translateECU("PKT_ECU_TELEMETRY_SETTINGS"); + case PKT_ECU_PUMP_CONFIG: + return translateECU("PKT_ECU_PUMP_CONFIG"); + case PKT_ECU_ERROR_MSG: + return translateECU("PKT_ECU_ERROR_MSG"); + case PKT_ECU_POWER_CYCLES: + return translateECU("PKT_ECU_POWER_CYCLES"); + case PKT_ECU_PUMP_2_CONFIG: + return translateECU("PKT_ECU_PUMP_2_CONFIG"); + case PKT_ECU_PUMP_DEBUG: + return translateECU("PKT_ECU_PUMP_DEBUG"); + case PKT_ECU_TOTAL_ENGINE_TIME: + return translateECU("PKT_ECU_TOTAL_ENGINE_TIME"); + case PKT_ECU_SYS_CMD: + return translateECU("PKT_ECU_SYS_CMD"); + case PKT_ECU_USER_DATA: + return translateECU("PKT_ECU_USER_DATA"); + case PKT_ECU_THROTTLE_CURVE_0: + return translateECU("PKT_ECU_THROTTLE_CURVE_0"); + case PKT_ECU_THROTTLE_CURVE_1: + return translateECU("PKT_ECU_THROTTLE_CURVE_1"); + case PKT_ECU_GPIO: + return translateECU("PKT_ECU_GPIO"); + case PKT_ECU_SETTINGS_DATA: + return translateECU("PKT_ECU_SETTINGS_DATA"); + case PKT_ECU_CHT_LOOP: + return translateECU("PKT_ECU_CHT_LOOP"); + } +} + + +/*! + * \brief Lookup label for 'ECUSystemCommands' enum entry + * + * \param value is the integer value of the enum entry + * \return string label of the given entry + */ +const char* ECUSystemCommands_EnumLabel(int value) +{ + switch (value) + { + default: + return ""; + case CMD_ECU_CALIBRATE_ANALOG_CLOSED: + return translateECU("CMD_ECU_CALIBRATE_ANALOG_CLOSED"); + case CMD_ECU_CALIBRATE_ANALOG_OPEN: + return translateECU("CMD_ECU_CALIBRATE_ANALOG_OPEN"); + case CMD_ECU_CALIBRATE_PULSE_CLOSED: + return translateECU("CMD_ECU_CALIBRATE_PULSE_CLOSED"); + case CMD_ECU_CALIBRATE_PULSE_OPEN: + return translateECU("CMD_ECU_CALIBRATE_PULSE_OPEN"); + case CMD_ECU_CALIBRATE_PULSE_WRITE: + return translateECU("CMD_ECU_CALIBRATE_PULSE_WRITE"); + case CMD_ECU_SET_OUTPUT_DRIVER: + return translateECU("CMD_ECU_SET_OUTPUT_DRIVER"); + case CMD_ECU_SET_THROTTLE_CURVE_ACTIVE: + return translateECU("CMD_ECU_SET_THROTTLE_CURVE_ACTIVE"); + case CMD_ECU_SET_THROTTLE_CURVE_ELEMENT: + return translateECU("CMD_ECU_SET_THROTTLE_CURVE_ELEMENT"); + case CMD_ECU_REQUEST_THROTTLE_CURVE_DATA: + return translateECU("CMD_ECU_REQUEST_THROTTLE_CURVE_DATA"); + case CMD_ECU_RESET_FUEL_USED: + return translateECU("CMD_ECU_RESET_FUEL_USED"); + case CMD_ECU_SET_FUEL_USED_DIVISOR: + return translateECU("CMD_ECU_SET_FUEL_USED_DIVISOR"); + case CMD_ECU_FUEL_USED_RESET_ON_STARTUP: + return translateECU("CMD_ECU_FUEL_USED_RESET_ON_STARTUP"); + case CMD_ECU_SET_GOVERNOR_MODE: + return translateECU("CMD_ECU_SET_GOVERNOR_MODE"); + case CMD_ECU_SET_SERVO_CAN_MODE: + return translateECU("CMD_ECU_SET_SERVO_CAN_MODE"); + case CMD_ECU_RESET_INTO_BOOTLOADER: + return translateECU("CMD_ECU_RESET_INTO_BOOTLOADER"); + case CMD_ECU_RESET_DEFAULT_SETTINGS: + return translateECU("CMD_ECU_RESET_DEFAULT_SETTINGS"); + case CMD_ECU_SET_SERIAL_MODE: + return translateECU("CMD_ECU_SET_SERIAL_MODE"); + case CMD_ECU_SET_NODE_ID: + return translateECU("CMD_ECU_SET_NODE_ID"); + case CMD_ECU_SET_USER_DATA: + return translateECU("CMD_ECU_SET_USER_DATA"); + case CMD_ECU_RESET_ENGINE_TIME: + return translateECU("CMD_ECU_RESET_ENGINE_TIME"); + case CMD_ECU_RESET_ECU: + return translateECU("CMD_ECU_RESET_ECU"); + } +} + +// end of ECUProtocol.c diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUProtocol.h b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUProtocol.h new file mode 100644 index 0000000000..d5011f3bdb --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUProtocol.h @@ -0,0 +1,211 @@ +// ECUProtocol.h was generated by ProtoGen version 3.2.a + +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Author: Oliver Walters / Currawong Engineering Pty Ltd + */ + + +#ifndef _ECUPROTOCOL_H +#define _ECUPROTOCOL_H + +// Language target is C, C++ compilers: don't mangle us +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \mainpage ECU protocol stack + * + * ECU ICD + * + * The protocol API enumeration is incremented anytime the protocol is changed + * in a way that affects compatibility with earlier versions of the protocol. + * The protocol enumeration for this version is: 11 + * + * The protocol version is 7.0 + */ + +#include +#include + +//! \return the protocol API enumeration +#define getECUApi() 11 + +//! \return the protocol version string +#define getECUVersion() "7.0" + +// Translation provided externally. The macro takes a `const char *` and returns a `const char *` +#ifndef translateECU + #define translateECU(x) x +#endif + +/*! + * Enumeration defining RESET commands for ECU settings + */ +typedef enum +{ + ECU_RESET_THROTTLE = 0x01,//!< Reset throttle settings to default values + ECU_RESET_PUMP = 0x02, //!< Reset pump settings to default values + ECU_RESET_GOVERNOR = 0x04,//!< Reset governor settings to default values + ECU_RESET_TELEMETRY = 0x08,//!< Reset telemetry settings to default values + ECU_RESET_ALL = 0xFF //!< Reset all ECU settings to default values +} ECUResetCommands; + +typedef enum +{ + ECU_DEBUG_RESET_STACK_OVERFLOW = 0x01, + ECU_DEBUG_RESET_STACK_UNDERFLOW, + ECU_DEBUG_RESET_DIVIDE_BY_ZERO, + ECU_DEBUG_RESET_INFINITE_LOOP +} ECUDebugResetTests; + +/*! + * ECU throttle position signal source enumeration + */ +typedef enum +{ + ECU_TPS_SRC_NONE = 0x00, //!< No throttle source + ECU_TPS_SRC_RPM = 0x01, //!< Throttle is commanded by RPM governor + ECU_TPS_SRC_PWM = 0x02, //!< Throttle is commanded from PWM input + ECU_TPS_SRC_SERIAL = 0x04,//!< Throttle is commanded from serial command packet + ECU_TPS_SRC_CAN = 0x08, //!< Throttle is commanded from CAN command packet + ECU_TPS_SRC_ANALOG = 0x0F //!< Throttle is commanded from analog input +} ECUThrottleSource; + +typedef enum +{ + ECU_DUAL_PUMP_MODE_DISABLED = 0x00,//!< Both pumps disabled + ECU_DUAL_PUMP_MODE_PRIMARY_CE, //!< Primary pump running + ECU_DUAL_PUMP_MODE_SECONDARY_TSA,//!< Secondary pump running + ECU_DUAL_PUMP_MODE_BOTH //!< Both pumps running +} DualFuelPumpMode; + +typedef enum +{ + ECU_DUAL_PUMP_STATE_RESET = 0x00,//!< Pump state machine is in the initial reset state + ECU_DUAL_PUMP_STATE_CMD, //!< Pump was explicitly commanded to the current state + ECU_DUAL_PUMP_STATE_TEST, //!< Pump is running in manual test mode + ECU_DUAL_PUMP_STATE_FAILURE //!< Pump has switched over due to detected failure +} DualFuelPumpState; + +typedef enum +{ + ECU_DUAL_PUMP_CMD_SET_PUMP = 0x01,//!< Switch to a particular pump mode + ECU_DUAL_PUMP_CMD_TEST_PUMP = 0x02 //!< Temporarily switch to a particular pump mode +} DualFuelPumpCommands; + +/*! + * ECU packet identifier (ID) definitions + */ +typedef enum +{ + PKT_ECU_TELEMETRY_FAST = 0x00, //!< High priority telemetry data from the ECU + PKT_ECU_TELEMETRY_SLOW_0, //!< First low priority telemetry packet from the ECU + PKT_ECU_TELEMETRY_SLOW_1, //!< Second low priority telemetry packet from the ECU + PKT_ECU_TELEMETRY_SLOW_2, //!< Third low priority telemetry packet from the ECU + PKT_ECU_TELEMETRY_SLOW_3, //!< Fourth low priority telemetry packet from the ECU (reserved for future use) + PKT_ECU_THROTTLE_CALIBRATION = 0x05, //!< Throttle calibration values + PKT_ECU_THROTTLE, //!< ECU throttle command + PKT_ECU_THROTTLE_COMBINED, //!< ECU Throttle command (position and pulse) + PKT_ECU_RPM_COMMAND, //!< RPM setpoint command + PKT_ECU_RPM_CALIBRATION, //!< RPM control loop calibration values + PKT_ECU_HARDWARE_CONFIG, //!< Serial number information + PKT_ECU_SOFTWARE_VERSION, //!< Firmware version information + PKT_ECU_TPS_DELAY_CONFIG, //!< Throttle delay configuration + PKT_ECU_TELEMETRY_SETTINGS, //!< Telemetry configuration + PKT_ECU_PUMP_CONFIG, //!< ECU Pump configuration packet 1 of 2 + PKT_ECU_ERROR_MSG, //!< Error messages + PKT_ECU_POWER_CYCLES = 0x10, //!< System information + PKT_ECU_PUMP_2_CONFIG, //!< ECU Pump configuration packet 2 of 2 + PKT_ECU_PUMP_DEBUG, //!< Pump debug information + PKT_ECU_TOTAL_ENGINE_TIME, //!< Total engine run-time + PKT_ECU_SYS_CMD, //!< ECU System command + PKT_ECU_USER_DATA, //!< User-configurable data bytes + PKT_ECU_THROTTLE_CURVE_0, //!< Throttle curve data, packet 1 of 2 + PKT_ECU_THROTTLE_CURVE_1, //!< Throttle curve data, packet 2 of 2 + PKT_ECU_GPIO, //!< GPIO settings + PKT_ECU_SETTINGS_DATA, //!< Non-volatile settings information + PKT_ECU_AUTRONIC_MEMORY, //!< Read or write Autronic RAM + PKT_ECU_CHT_LOOP, //!< Control loop settings for the CHT control loop + PKT_ECU_CANAUTRONIC_RELAY = 0x1F //!< Relay Autronic data across CAN +} ECUPackets; + +//! \return the label of a 'ECUPackets' enum entry, based on its value +const char* ECUPackets_EnumLabel(int value); + +typedef enum +{ + ECU_CE_CAL_TITLE_1 = 0xA0, + ECU_CE_CAL_TITLE_2, + ECU_CE_CAL_TITLE_3 +} ECUSpecialPackets; + +/*! + * These system command identifiers are used with the [system + * command](#PKT_ECU_SYS_CMD) packet. + */ +typedef enum +{ + CMD_ECU_CALIBRATE_ANALOG_CLOSED = 0x01,//!< Save the current value of the analog throttle position input as the 'Closed' position. To calibrate the closed analog input position, set the desired analog input level, and send this command to the ECU. + CMD_ECU_CALIBRATE_ANALOG_OPEN, //!< Save the current value of the analog throttle position input as the 'Open' position. To calibrate the open analog input position, set the desired analog input level, and send this command to the ECU. + CMD_ECU_CALIBRATE_PULSE_CLOSED, //!< Save the current value of the throttle output pulse width to a temporary variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the ECU, this value will be saved as the 'Closed' pulse width. + CMD_ECU_CALIBRATE_PULSE_OPEN, //!< Save the current value of the throttle output pulse width to a temporary variable in the ECU. When the CALIBRATE_PULSE_WRITE command is sent to the ECU, this value will be saved as the 'Open' pulse width. + CMD_ECU_CALIBRATE_PULSE_WRITE, //!< Configure the throttle output positions. The CALIBRATE_PULSE_CLOSED and CALIBRATE_PULSE_OPEN commands should have already been sent to the ECU. The ECU then saves the temporary values as the 'Closed' and 'Open' throttle output values, respectively. + CMD_ECU_SET_OUTPUT_DRIVER = 0x0A, //!< Set one of four high-current output drivers. Send two bytes after the command byte. Byte 1: Driver - Select driver number (1, 2, 3 or 4) Byte 2: Status - Set driver status (1 = ON, 0 = OFF) + CMD_ECU_SET_THROTTLE_CURVE_ACTIVE, //!< Turn the throttle linearization curve either on or off. Byte 1: 1 = ON 0 = OFF + CMD_ECU_SET_THROTTLE_CURVE_ELEMENT, //!< Set individual elements in the throttle linearization lookup table. Byte 1 = Element number (0 to 10, inclusive) Byte 2 = Value (0 to 200 inclusive) Each bit of the 'value' byte represents 0.5% throttle. So, 0 = 0% and 200 = 100% + CMD_ECU_REQUEST_THROTTLE_CURVE_DATA, //!< Request the throttle curve lookup table data. If requested on CAN, the data will be returned on CAN. If requested on RS232, the data will be returned on RS232. + CMD_ECU_RESET_FUEL_USED = 0x10, //!< Reset the FuelUsed value. This will set the FuelUsed data to zero. + CMD_ECU_SET_FUEL_USED_DIVISOR, //!< Configure the FuelUsed divisor. This is an unsigned 16-bit value. The fuel used value is divided by this divisor before being transmitted by the auxiliary processor. Set this value to 1 to leave the fuel used data unaffected. If you use values greater than 100 the divisor is automatically interpreted as being in units of 0.01 (i.e. 100 times the resolution). + CMD_ECU_FUEL_USED_RESET_ON_STARTUP, //!< Set or clear the Fuel Used reset flag. If this flag is set, the FuelUsed data will reset (to zero) when the ECU is power cycled. 1 = Reset Fuel Used data on powerup 0 = Do not reset Fuel Used data on power up + CMD_ECU_SET_GOVERNOR_MODE = 0x20, //!< Manually set the RPM governor mode Byte1 = MODE 0 = Governor Off (Open loop throttle control) 1 = Governor based on throttle command 2 = Governor based on RPM command + CMD_ECU_SET_SERVO_CAN_MODE = 0x28, + CMD_ECU_RESET_INTO_BOOTLOADER = 0x30,//!< Reset the ECU into bootloader mode + CMD_ECU_RESET_DEFAULT_SETTINGS, //!< Set ECU settings to their default values + CMD_ECU_SET_SERIAL_MODE = 0x40, //!< Set the serial relay mode used for Autronic relay + CMD_ECU_SET_NODE_ID = 0x50, //!< Set the address (CAN node ID) for the ECU + CMD_ECU_SET_USER_DATA = 0x60, //!< Save a single byte of USER_DATA in EEPROM Byte1 = USER_DATA address (0 to 7) Byte2 = USER_DATA variable (0x00 to 0xFF) + CMD_ECU_RESET_ENGINE_TIME = 0xA5, //!< Reset the engine time counter. If no further bytes are sent after the RESET_ENGINE_TIME command, this will set the engine time (in seconds) to zero. Note that the 'Total Engine Time' counter is not reset. To set the engine time to a specific value, send the engine time in seconds as a 3-byte (big endian) number after the RESET_ENGINE_TIME command. + CMD_ECU_RESET_ECU = 0xD0 //!< Cause a system reset +} ECUSystemCommands; + +//! \return the label of a 'ECUSystemCommands' enum entry, based on its value +const char* ECUSystemCommands_EnumLabel(int value); + + +// The prototypes below provide an interface to the packets. +// They are not auto-generated functions, but must be hand-written + +//! \return the packet data pointer from the packet +uint8_t* getECUPacketData(void* pkt); + +//! \return the packet data pointer from the packet, const +const uint8_t* getECUPacketDataConst(const void* pkt); + +//! Complete a packet after the data have been encoded +void finishECUPacket(void* pkt, int size, uint32_t packetID); + +//! \return the size of a packet from the packet header +int getECUPacketSize(const void* pkt); + +//! \return the ID of a packet from the packet header +uint32_t getECUPacketID(const void* pkt); + +#ifdef __cplusplus +} +#endif +#endif // _ECUPROTOCOL_H diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUSettings.c b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUSettings.c new file mode 100644 index 0000000000..88c91e9eee --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUSettings.c @@ -0,0 +1,642 @@ +// ECUSettings.c was generated by ProtoGen version 3.2.a + +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Author: Oliver Walters / Currawong Engineering Pty Ltd + */ + + +#include "ECUSettings.h" +#include "fielddecode.h" +#include "fieldencode.h" +#include "scaleddecode.h" +#include "scaledencode.h" + +/*! + * \brief Encode a ECU_PumpOptionBits_t into a byte array + * + + * \param _pg_data points to the byte array to add encoded data to + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of encoded bytes. + * \param _pg_user is the data to encode in the byte array + */ +void encodeECU_PumpOptionBits_t(uint8_t* _pg_data, int* _pg_bytecount, const ECU_PumpOptionBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Reserved for future use + // Range of reserved is 0 to 255. + _pg_data[_pg_byteindex] = (uint8_t)_pg_user->reserved; + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + +}// encodeECU_PumpOptionBits_t + +/*! + * \brief Decode a ECU_PumpOptionBits_t from a byte array + * + + * \param _pg_data points to the byte array to decoded data from + * \param _pg_bytecount points to the starting location in the byte array, and will be incremented by the number of bytes decoded + * \param _pg_user is the data to decode from the byte array + * \return 1 if the data are decoded, else 0. + */ +int decodeECU_PumpOptionBits_t(const uint8_t* _pg_data, int* _pg_bytecount, ECU_PumpOptionBits_t* _pg_user) +{ + int _pg_byteindex = *_pg_bytecount; + + // Reserved for future use + // Range of reserved is 0 to 255. + _pg_user->reserved = _pg_data[_pg_byteindex]; + _pg_byteindex += 1; // close bit field + + *_pg_bytecount = _pg_byteindex; + + return 1; + +}// decodeECU_PumpOptionBits_t + +/*! + * \brief Create the ECU_ThrottleSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_ThrottleSettingsPacketStructure(void* _pg_pkt, const ECU_ThrottleSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned int _pg_tempbitfield = 0; + unsigned _pg_i = 0; + + // Throttle open PWM value + // Range of pulseOpen is 0 to 65535. + uint16ToBeBytes(_pg_user->pulseOpen, _pg_data, &_pg_byteindex); + + // Throttle closed PWM value + // Range of pulseClosed is 0 to 65535. + uint16ToBeBytes(_pg_user->pulseClosed, _pg_data, &_pg_byteindex); + + // Throttle input open PWM value + // Range of pulseInputOpen is 0 to 4095. + _pg_tempbitfield = (unsigned int)limitMax(_pg_user->pulseInputOpen, 4095); + _pg_data[_pg_byteindex + 1] = (uint8_t)(_pg_tempbitfield << 4); + + _pg_tempbitfield >>= 4; + _pg_data[_pg_byteindex] = (uint8_t)_pg_tempbitfield; + + + // Throttle input closed PWM value + // Range of pulseInputClosed is 0 to 4095. + _pg_tempbitfield = (unsigned int)limitMax(_pg_user->pulseInputClosed, 4095); + _pg_data[_pg_byteindex + 2] = (uint8_t)_pg_tempbitfield; + + _pg_tempbitfield >>= 8; + _pg_data[_pg_byteindex + 1] |= (uint8_t)_pg_tempbitfield; + _pg_byteindex += 3; // close bit field + + + // Throttle delay, constant value + // Range of delay is 0 to 255. + uint8ToBytes(_pg_user->delay, _pg_data, &_pg_byteindex); + + // Throttle delay, minimum value + // Range of minDelay is 0 to 255. + uint8ToBytes(_pg_user->minDelay, _pg_data, &_pg_byteindex); + + // Throttle delay, minimum value + // Range of maxDelay is 0 to 255. + uint8ToBytes(_pg_user->maxDelay, _pg_data, &_pg_byteindex); + + encodeECU_ThrottleDelayConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->delayConfig); + + // Throttle dashpot soft limit value + // Range of softLimit is 0 to 255. + uint8ToBytes(_pg_user->softLimit, _pg_data, &_pg_byteindex); + + // Throttle dashpot hard limit value + // Range of hardLimit is 0 to 255. + uint8ToBytes(_pg_user->hardLimit, _pg_data, &_pg_byteindex); + + // Throttle dashpot falloff rate + // Range of falloffRate is 0 to 255. + uint8ToBytes(_pg_user->falloffRate, _pg_data, &_pg_byteindex); + + // Throttle curve lookup table elements + // Range of curve is 0 to 255. + for(_pg_i = 0; _pg_i < 11; _pg_i++) + uint8ToBytes(_pg_user->curve[_pg_i], _pg_data, &_pg_byteindex); + + // Throttle curve config bits + encodeECU_ThrottleCurveConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->curveConfig); + + encodeECU_ThrottleConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->config); + + // Range of analogSpan1 is 0 to 255. + uint8ToBytes(_pg_user->analogSpan1, _pg_data, &_pg_byteindex); + + // Range of analogSpan2 is 0 to 65535. + uint16ToBeBytes(_pg_user->analogSpan2, _pg_data, &_pg_byteindex); + + // Range of throttleTarget is 0 to 255. + uint8ToBytes(_pg_user->throttleTarget, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ThrottleSettingsPacketID()); + +}// encodeECU_ThrottleSettingsPacketStructure + +/*! + * \brief Decode the ECU_ThrottleSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ThrottleSettingsPacketStructure(const void* _pg_pkt, ECU_ThrottleSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + unsigned int _pg_tempbitfield = 0; + unsigned _pg_i = 0; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ThrottleSettingsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_ThrottleSettingsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Throttle open PWM value + // Range of pulseOpen is 0 to 65535. + _pg_user->pulseOpen = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Throttle closed PWM value + // Range of pulseClosed is 0 to 65535. + _pg_user->pulseClosed = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Throttle input open PWM value + // Range of pulseInputOpen is 0 to 4095. + _pg_tempbitfield = (_pg_data[_pg_byteindex] & 0xFF); + + _pg_tempbitfield <<= 4; + _pg_tempbitfield |= (_pg_data[_pg_byteindex + 1] >> 4); + + _pg_user->pulseInputOpen = _pg_tempbitfield; + + // Throttle input closed PWM value + // Range of pulseInputClosed is 0 to 4095. + _pg_tempbitfield = (_pg_data[_pg_byteindex + 1] & 0xF); + + _pg_tempbitfield <<= 8; + _pg_tempbitfield |= _pg_data[_pg_byteindex + 2]; + + _pg_user->pulseInputClosed = _pg_tempbitfield; + _pg_byteindex += 3; // close bit field + + // Throttle delay, constant value + // Range of delay is 0 to 255. + _pg_user->delay = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle delay, minimum value + // Range of minDelay is 0 to 255. + _pg_user->minDelay = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle delay, minimum value + // Range of maxDelay is 0 to 255. + _pg_user->maxDelay = uint8FromBytes(_pg_data, &_pg_byteindex); + + if(decodeECU_ThrottleDelayConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->delayConfig) == 0) + return 0; + + // Throttle dashpot soft limit value + // Range of softLimit is 0 to 255. + _pg_user->softLimit = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle dashpot hard limit value + // Range of hardLimit is 0 to 255. + _pg_user->hardLimit = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle dashpot falloff rate + // Range of falloffRate is 0 to 255. + _pg_user->falloffRate = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle curve lookup table elements + // Range of curve is 0 to 255. + for(_pg_i = 0; _pg_i < 11; _pg_i++) + _pg_user->curve[_pg_i] = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Throttle curve config bits + if(decodeECU_ThrottleCurveConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->curveConfig) == 0) + return 0; + + if(decodeECU_ThrottleConfigBits_t(_pg_data, &_pg_byteindex, &_pg_user->config) == 0) + return 0; + + // Range of analogSpan1 is 0 to 255. + _pg_user->analogSpan1 = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Range of analogSpan2 is 0 to 65535. + _pg_user->analogSpan2 = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of throttleTarget is 0 to 255. + _pg_user->throttleTarget = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_ThrottleSettingsPacketStructure + +/*! + * \brief Create the ECU_FuelUsedSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_FuelUsedSettingsPacketStructure(void* _pg_pkt, const ECU_FuelUsedSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Range of resetOnStartup is 0 to 255. + uint8ToBytes(_pg_user->resetOnStartup, _pg_data, &_pg_byteindex); + + // Range of divisor is 0 to 65535. + uint16ToBeBytes(_pg_user->divisor, _pg_data, &_pg_byteindex); + + // Range of offset is 0 to 65535. + uint16ToBeBytes(_pg_user->offset, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_FuelUsedSettingsPacketID()); + +}// encodeECU_FuelUsedSettingsPacketStructure + +/*! + * \brief Decode the ECU_FuelUsedSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_FuelUsedSettingsPacketStructure(const void* _pg_pkt, ECU_FuelUsedSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_FuelUsedSettingsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_FuelUsedSettingsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Range of resetOnStartup is 0 to 255. + _pg_user->resetOnStartup = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Range of divisor is 0 to 65535. + _pg_user->divisor = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of offset is 0 to 65535. + _pg_user->offset = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_FuelUsedSettingsPacketStructure + +/*! + * \brief Create the ECU_GovernorSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_GovernorSettingsPacketStructure(void* _pg_pkt, const ECU_GovernorSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Range of pGain is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->pGain, _pg_data, &_pg_byteindex); + + // Range of iGain is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->iGain, _pg_data, &_pg_byteindex); + + // Range of dGain is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->dGain, _pg_data, &_pg_byteindex); + + // Range of scalePower is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->scalePower, _pg_data, &_pg_byteindex); + + // Range of maxRPM is 0.0f to 25500.0f. + float32ScaledTo1UnsignedBytes(_pg_user->maxRPM, _pg_data, &_pg_byteindex, 0.0f, 0.01f); + + // Range of minRPM is 0.0f to 25500.0f. + float32ScaledTo1UnsignedBytes(_pg_user->minRPM, _pg_data, &_pg_byteindex, 0.0f, 0.01f); + + // Range of mode is 0 to 255. + uint8ToBytes(_pg_user->mode, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_GovernorSettingsPacketID()); + +}// encodeECU_GovernorSettingsPacketStructure + +/*! + * \brief Decode the ECU_GovernorSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_GovernorSettingsPacketStructure(const void* _pg_pkt, ECU_GovernorSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_GovernorSettingsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_GovernorSettingsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Range of pGain is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->pGain = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of iGain is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->iGain = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of dGain is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->dGain = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of scalePower is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->scalePower = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of maxRPM is 0.0f to 25500.0f. + _pg_user->maxRPM = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/0.01f); + + // Range of minRPM is 0.0f to 25500.0f. + _pg_user->minRPM = float32ScaledFrom1UnsignedBytes(_pg_data, &_pg_byteindex, 0.0f, 1.0f/0.01f); + + // Range of mode is 0 to 255. + _pg_user->mode = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_GovernorSettingsPacketStructure + +/*! + * \brief Create the ECU_PumpSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_PumpSettingsPacketStructure(void* _pg_pkt, const ECU_PumpSettings_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + + // Pump proportional gain + // Range of kp is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->kp, _pg_data, &_pg_byteindex); + + // Pump integral gain + // Range of ki is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->ki, _pg_data, &_pg_byteindex); + + // Pump IMC (internal model) gain + // Range of km is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->km, _pg_data, &_pg_byteindex); + + // Pump lower pressure limit (PSI) + // Range of pressureLowerLimit is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->pressureLowerLimit, _pg_data, &_pg_byteindex); + + // Pump upper pressure limit (PSI) + // Range of pressureUpperLimit is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->pressureUpperLimit, _pg_data, &_pg_byteindex); + + // Fuel pressure setpoint + // Range of pressureSetpoint is -3.402823466e+38f to 3.402823466e+38f. + float32ToBeBytes((float)_pg_user->pressureSetpoint, _pg_data, &_pg_byteindex); + + // Range of minimumPWM is 0 to 255. + uint8ToBytes(_pg_user->minimumPWM, _pg_data, &_pg_byteindex); + + // Range of maximumPWM is 0 to 255. + uint8ToBytes(_pg_user->maximumPWM, _pg_data, &_pg_byteindex); + + // Pump duty cycle ramp rate + // Range of rampRate is 0 to 255. + uint8ToBytes(_pg_user->rampRate, _pg_data, &_pg_byteindex); + + // Pump control system options + encodeECU_PumpOptionBits_t(_pg_data, &_pg_byteindex, &_pg_user->options); + + // Reserved for future use + // Range of reservedA is 0 to 255. + uint8ToBytes(_pg_user->reservedA, _pg_data, &_pg_byteindex); + + // Reserved for future use + // Range of reservedB is 0 to 255. + uint8ToBytes(_pg_user->reservedB, _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_PumpSettingsPacketID()); + +}// encodeECU_PumpSettingsPacketStructure + +/*! + * \brief Decode the ECU_PumpSettings packet + * + * Throttle settings + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_PumpSettingsPacketStructure(const void* _pg_pkt, ECU_PumpSettings_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_PumpSettingsPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_PumpSettingsMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Pump proportional gain + // Range of kp is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->kp = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Pump integral gain + // Range of ki is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->ki = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Pump IMC (internal model) gain + // Range of km is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->km = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Pump lower pressure limit (PSI) + // Range of pressureLowerLimit is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->pressureLowerLimit = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Pump upper pressure limit (PSI) + // Range of pressureUpperLimit is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->pressureUpperLimit = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Fuel pressure setpoint + // Range of pressureSetpoint is -3.402823466e+38f to 3.402823466e+38f. + _pg_user->pressureSetpoint = float32FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of minimumPWM is 0 to 255. + _pg_user->minimumPWM = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Range of maximumPWM is 0 to 255. + _pg_user->maximumPWM = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Pump duty cycle ramp rate + // Range of rampRate is 0 to 255. + _pg_user->rampRate = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Pump control system options + if(decodeECU_PumpOptionBits_t(_pg_data, &_pg_byteindex, &_pg_user->options) == 0) + return 0; + + // Reserved for future use + // Range of reservedA is 0 to 255. + _pg_user->reservedA = uint8FromBytes(_pg_data, &_pg_byteindex); + + // Reserved for future use + // Range of reservedB is 0 to 255. + _pg_user->reservedB = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_PumpSettingsPacketStructure + +/*! + * \brief Create the ECU_ECUData packet + * + * User data + * \param _pg_pkt points to the packet which will be created by this function + * \param _pg_user points to the user data that will be encoded in _pg_pkt + */ +void encodeECU_ECUDataPacketStructure(void* _pg_pkt, const ECU_ECUData_t* _pg_user) +{ + uint8_t* _pg_data = getECUPacketData(_pg_pkt); + int _pg_byteindex = 0; + unsigned _pg_i = 0; + + // Range of powerCycles is 0 to 65535. + uint16ToBeBytes(_pg_user->powerCycles, _pg_data, &_pg_byteindex); + + // Range of engineTime is 0 to 4294967295. + uint32ToBeBytes(_pg_user->engineTime, _pg_data, &_pg_byteindex); + + // Range of engineTimeTotal is 0 to 4294967295. + uint32ToBeBytes(_pg_user->engineTimeTotal, _pg_data, &_pg_byteindex); + + // Range of fuelUsedOverflows is 0 to 65535. + uint16ToBeBytes(_pg_user->fuelUsedOverflows, _pg_data, &_pg_byteindex); + + // Range of userValues is 0 to 255. + for(_pg_i = 0; _pg_i < 8; _pg_i++) + uint8ToBytes(_pg_user->userValues[_pg_i], _pg_data, &_pg_byteindex); + + // complete the process of creating the packet + finishECUPacket(_pg_pkt, _pg_byteindex, getECU_ECUDataPacketID()); + +}// encodeECU_ECUDataPacketStructure + +/*! + * \brief Decode the ECU_ECUData packet + * + * User data + * \param _pg_pkt points to the packet being decoded by this function + * \param _pg_user receives the data decoded from the packet + * \return 0 is returned if the packet ID or size is wrong, else 1 + */ +int decodeECU_ECUDataPacketStructure(const void* _pg_pkt, ECU_ECUData_t* _pg_user) +{ + int _pg_numbytes; + int _pg_byteindex = 0; + const uint8_t* _pg_data; + unsigned _pg_i = 0; + + // Verify the packet identifier + if(getECUPacketID(_pg_pkt) != getECU_ECUDataPacketID()) + return 0; + + // Verify the packet size + _pg_numbytes = getECUPacketSize(_pg_pkt); + if(_pg_numbytes < getECU_ECUDataMinDataLength()) + return 0; + + // The raw data from the packet + _pg_data = getECUPacketDataConst(_pg_pkt); + + // Range of powerCycles is 0 to 65535. + _pg_user->powerCycles = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of engineTime is 0 to 4294967295. + _pg_user->engineTime = uint32FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of engineTimeTotal is 0 to 4294967295. + _pg_user->engineTimeTotal = uint32FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of fuelUsedOverflows is 0 to 65535. + _pg_user->fuelUsedOverflows = uint16FromBeBytes(_pg_data, &_pg_byteindex); + + // Range of userValues is 0 to 255. + for(_pg_i = 0; _pg_i < 8; _pg_i++) + _pg_user->userValues[_pg_i] = uint8FromBytes(_pg_data, &_pg_byteindex); + + return 1; + +}// decodeECU_ECUDataPacketStructure +// end of ECUSettings.c diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/ECUSettings.h b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUSettings.h new file mode 100644 index 0000000000..47d9c7d547 --- /dev/null +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/ECUSettings.h @@ -0,0 +1,224 @@ +// ECUSettings.h was generated by ProtoGen version 3.2.a + +/* + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Author: Oliver Walters / Currawong Engineering Pty Ltd + */ + + +#ifndef _ECUSETTINGS_H +#define _ECUSETTINGS_H + +// Language target is C, C++ compilers: don't mangle us +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + */ + +#include +#include "ECUProtocol.h" +#include "ECUDefines.h" +/*! + * ECU settings packets (not available on CAN or RS232 interfaces) + */ +typedef enum +{ + PKT_ECU_SETTINGS_THROTTLE = 0xF0, //!< Throttle settings + PKT_ECU_SETTINGS_PUMP = 0xF1, //!< Throttle settings + PKT_ECU_SETTINGS_GOVERNOR = 0xF2, //!< Throttle settings + PKT_ECU_SETTINGS_TELEMETRY = 0xF3, //!< Throttle settings + PKT_ECU_SETTINGS_FUEL_USED = 0xF4, //!< Throttle settings + PKT_ECU_SETTINGS_ENGINE_TIME = 0xF5, //!< Engine run time + PKT_ECU_SETTINGS_USER = 0xFA //!< User data +} ECUSettingsPackets; + +typedef struct +{ + unsigned reserved : 8; //!< Reserved for future use +}ECU_PumpOptionBits_t; + +//! return the minimum encoded length for the ECU_PumpOptionBits_t structure +#define getMinLengthOfECU_PumpOptionBits_t() (1) + +//! return the maximum encoded length for the ECU_PumpOptionBits_t structure +#define getMaxLengthOfECU_PumpOptionBits_t() (1) + +//! Encode a ECU_PumpOptionBits_t into a byte array +void encodeECU_PumpOptionBits_t(uint8_t* data, int* bytecount, const ECU_PumpOptionBits_t* user); + +//! Decode a ECU_PumpOptionBits_t from a byte array +int decodeECU_PumpOptionBits_t(const uint8_t* data, int* bytecount, ECU_PumpOptionBits_t* user); + +/*! + * Throttle settings + */ +typedef struct +{ + uint16_t pulseOpen; //!< Throttle open PWM value + uint16_t pulseClosed; //!< Throttle closed PWM value + uint16_t pulseInputOpen; //!< Throttle input open PWM value + uint16_t pulseInputClosed; //!< Throttle input closed PWM value + uint8_t delay; //!< Throttle delay, constant value + uint8_t minDelay; //!< Throttle delay, minimum value + uint8_t maxDelay; //!< Throttle delay, minimum value + ECU_ThrottleDelayConfigBits_t delayConfig; + uint8_t softLimit; //!< Throttle dashpot soft limit value + uint8_t hardLimit; //!< Throttle dashpot hard limit value + uint8_t falloffRate; //!< Throttle dashpot falloff rate + uint8_t curve[11]; //!< Throttle curve lookup table elements + ECU_ThrottleCurveConfigBits_t curveConfig; //!< Throttle curve config bits + ECU_ThrottleConfigBits_t config; + uint8_t analogSpan1; + uint16_t analogSpan2; + uint8_t throttleTarget; +}ECU_ThrottleSettings_t; + +//! Create the ECU_ThrottleSettings packet +void encodeECU_ThrottleSettingsPacketStructure(void* pkt, const ECU_ThrottleSettings_t* user); + +//! Decode the ECU_ThrottleSettings packet +int decodeECU_ThrottleSettingsPacketStructure(const void* pkt, ECU_ThrottleSettings_t* user); + +//! return the packet ID for the ECU_ThrottleSettings packet +#define getECU_ThrottleSettingsPacketID() (PKT_ECU_SETTINGS_THROTTLE) + +//! return the minimum encoded length for the ECU_ThrottleSettings packet +#define getECU_ThrottleSettingsMinDataLength() (31) + +//! return the maximum encoded length for the ECU_ThrottleSettings packet +#define getECU_ThrottleSettingsMaxDataLength() (31) + +/*! + * Throttle settings + */ +typedef struct +{ + uint8_t resetOnStartup; + uint16_t divisor; + uint16_t offset; +}ECU_FuelUsedSettings_t; + +//! Create the ECU_FuelUsedSettings packet +void encodeECU_FuelUsedSettingsPacketStructure(void* pkt, const ECU_FuelUsedSettings_t* user); + +//! Decode the ECU_FuelUsedSettings packet +int decodeECU_FuelUsedSettingsPacketStructure(const void* pkt, ECU_FuelUsedSettings_t* user); + +//! return the packet ID for the ECU_FuelUsedSettings packet +#define getECU_FuelUsedSettingsPacketID() (PKT_ECU_SETTINGS_FUEL_USED) + +//! return the minimum encoded length for the ECU_FuelUsedSettings packet +#define getECU_FuelUsedSettingsMinDataLength() (5) + +//! return the maximum encoded length for the ECU_FuelUsedSettings packet +#define getECU_FuelUsedSettingsMaxDataLength() (5) + +/*! + * Throttle settings + */ +typedef struct +{ + float pGain; + float iGain; + float dGain; + float scalePower; + float maxRPM; + float minRPM; + uint8_t mode; +}ECU_GovernorSettings_t; + +//! Create the ECU_GovernorSettings packet +void encodeECU_GovernorSettingsPacketStructure(void* pkt, const ECU_GovernorSettings_t* user); + +//! Decode the ECU_GovernorSettings packet +int decodeECU_GovernorSettingsPacketStructure(const void* pkt, ECU_GovernorSettings_t* user); + +//! return the packet ID for the ECU_GovernorSettings packet +#define getECU_GovernorSettingsPacketID() (PKT_ECU_SETTINGS_GOVERNOR) + +//! return the minimum encoded length for the ECU_GovernorSettings packet +#define getECU_GovernorSettingsMinDataLength() (19) + +//! return the maximum encoded length for the ECU_GovernorSettings packet +#define getECU_GovernorSettingsMaxDataLength() (19) + +/*! + * Throttle settings + */ +typedef struct +{ + float kp; //!< Pump proportional gain + float ki; //!< Pump integral gain + float km; //!< Pump IMC (internal model) gain + float pressureLowerLimit; //!< Pump lower pressure limit (PSI) + float pressureUpperLimit; //!< Pump upper pressure limit (PSI) + float pressureSetpoint; //!< Fuel pressure setpoint + uint8_t minimumPWM; + uint8_t maximumPWM; + uint8_t rampRate; //!< Pump duty cycle ramp rate + ECU_PumpOptionBits_t options; //!< Pump control system options + uint8_t reservedA; //!< Reserved for future use + uint8_t reservedB; //!< Reserved for future use +}ECU_PumpSettings_t; + +//! Create the ECU_PumpSettings packet +void encodeECU_PumpSettingsPacketStructure(void* pkt, const ECU_PumpSettings_t* user); + +//! Decode the ECU_PumpSettings packet +int decodeECU_PumpSettingsPacketStructure(const void* pkt, ECU_PumpSettings_t* user); + +//! return the packet ID for the ECU_PumpSettings packet +#define getECU_PumpSettingsPacketID() (PKT_ECU_SETTINGS_PUMP) + +//! return the minimum encoded length for the ECU_PumpSettings packet +#define getECU_PumpSettingsMinDataLength() (30) + +//! return the maximum encoded length for the ECU_PumpSettings packet +#define getECU_PumpSettingsMaxDataLength() (30) + +/*! + * User data + */ +typedef struct +{ + uint16_t powerCycles; + uint32_t engineTime; + uint32_t engineTimeTotal; + uint16_t fuelUsedOverflows; + uint8_t userValues[8]; +}ECU_ECUData_t; + +//! Create the ECU_ECUData packet +void encodeECU_ECUDataPacketStructure(void* pkt, const ECU_ECUData_t* user); + +//! Decode the ECU_ECUData packet +int decodeECU_ECUDataPacketStructure(const void* pkt, ECU_ECUData_t* user); + +//! return the packet ID for the ECU_ECUData packet +#define getECU_ECUDataPacketID() (PKT_ECU_SETTINGS_USER) + +//! return the minimum encoded length for the ECU_ECUData packet +#define getECU_ECUDataMinDataLength() (20) + +//! return the maximum encoded length for the ECU_ECUData packet +#define getECU_ECUDataMaxDataLength() (20) + +#ifdef __cplusplus +} +#endif +#endif // _ECUSETTINGS_H diff --git a/libraries/AP_PiccoloCAN/piccolo_protocol/license.txt b/libraries/AP_PiccoloCAN/piccolo_protocol/license.txt index 266877bcc6..61a7ef22ec 100644 --- a/libraries/AP_PiccoloCAN/piccolo_protocol/license.txt +++ b/libraries/AP_PiccoloCAN/piccolo_protocol/license.txt @@ -12,5 +12,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see . * + * This license applies to all files in this directory. + * * Author: Oliver Walters */