Add new CanTxMessage class, consume in OBD2 (#1186)
* relocate * include path * simulator makefile * fix mre while we're at it * it would help if I fixed it right * add can_msg * convert obd2 * guard properly * better include order * docs & headers * inject CAN device Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
f43042d61b
commit
1b4d98a7f0
|
@ -30,7 +30,7 @@
|
|||
#include "os_access.h"
|
||||
#include "engine.h"
|
||||
#include "obd2.h"
|
||||
#include "can_hw.h"
|
||||
#include "can_msg_tx.h"
|
||||
#include "vehicle_speed.h"
|
||||
#include "map.h"
|
||||
#include "maf.h"
|
||||
|
@ -39,8 +39,6 @@
|
|||
#include "fuel_math.h"
|
||||
#include "thermistors.h"
|
||||
|
||||
extern CANTxFrame txmsg;
|
||||
|
||||
EXTERN_ENGINE
|
||||
;
|
||||
|
||||
|
@ -70,19 +68,17 @@ static const int16_t supportedPids4160[] = {
|
|||
};
|
||||
|
||||
static void obdSendPacket(int mode, int PID, int numBytes, uint32_t iValue) {
|
||||
commonTxInit(OBD_TEST_RESPONSE);
|
||||
CanTxMessage resp(OBD_TEST_RESPONSE);
|
||||
|
||||
// write number of bytes
|
||||
txmsg.data8[0] = (uint8_t)(2 + numBytes);
|
||||
resp[0] = (uint8_t)(2 + numBytes);
|
||||
// write 2 bytes of header
|
||||
txmsg.data8[1] = (uint8_t)(0x40 + mode);
|
||||
txmsg.data8[2] = (uint8_t)PID;
|
||||
resp[1] = (uint8_t)(0x40 + mode);
|
||||
resp[2] = (uint8_t)PID;
|
||||
// write N data bytes
|
||||
for (int i = 8 * (numBytes - 1), j = 3; i >= 0; i -= 8, j++) {
|
||||
txmsg.data8[j] = (uint8_t)((iValue >> i) & 0xff);
|
||||
resp[j] = (uint8_t)((iValue >> i) & 0xff);
|
||||
}
|
||||
|
||||
sendCanMessage();
|
||||
}
|
||||
|
||||
static void obdSendValue(int mode, int PID, int numBytes, float value) {
|
||||
|
@ -185,13 +181,15 @@ static void handleGetDataRequest(CANRxFrame *rx) {
|
|||
}
|
||||
|
||||
static void handleDtcRequest(int numCodes, int *dtcCode) {
|
||||
int numBytes = numCodes * 2;
|
||||
// write CAN-TP Single Frame header?
|
||||
txmsg.data8[0] = (uint8_t)((0 << 4) | numBytes);
|
||||
for (int i = 0, j = 1; i < numCodes; i++) {
|
||||
txmsg.data8[j++] = (uint8_t)((dtcCode[i] >> 8) & 0xff);
|
||||
txmsg.data8[j++] = (uint8_t)(dtcCode[i] & 0xff);
|
||||
}
|
||||
// TODO: this appears to be unfinished?
|
||||
|
||||
// int numBytes = numCodes * 2;
|
||||
// // write CAN-TP Single Frame header?
|
||||
// txmsg.data8[0] = (uint8_t)((0 << 4) | numBytes);
|
||||
// for (int i = 0, j = 1; i < numCodes; i++) {
|
||||
// txmsg.data8[j++] = (uint8_t)((dtcCode[i] >> 8) & 0xff);
|
||||
// txmsg.data8[j++] = (uint8_t)(dtcCode[i] & 0xff);
|
||||
// }
|
||||
}
|
||||
|
||||
#if HAL_USE_CAN
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "periodic_thread_controller.h"
|
||||
#include "pin_repository.h"
|
||||
#include "can_hw.h"
|
||||
#include "can_msg_tx.h"
|
||||
#include "string.h"
|
||||
#include "obd2.h"
|
||||
#include "mpu_util.h"
|
||||
|
@ -369,6 +370,12 @@ void initCan(void) {
|
|||
canStart(&CAND1, &canConfig500);
|
||||
#endif /* STM32_CAN_USE_CAN2 */
|
||||
|
||||
// Plumb CAN device to tx system
|
||||
CanTxMessage::setDevice(detectCanDevice(
|
||||
CONFIG(canRxPin),
|
||||
CONFIG(canTxPin)
|
||||
));
|
||||
|
||||
// fire up threads, as necessary
|
||||
if (CONFIG(canWriteEnabled)) {
|
||||
canWrite.setPeriod(CONFIG(canSleepPeriodMs));
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* @file can_msg_tx.cpp
|
||||
*
|
||||
* CAN message transmission
|
||||
*
|
||||
* @date Mar 13, 2020
|
||||
* @author Matthew Kennedy, (c) 2012-2020
|
||||
*/
|
||||
|
||||
#include "efifeatures.h"
|
||||
#include "global.h"
|
||||
|
||||
#if EFI_CAN_SUPPORT
|
||||
#include "can_msg_tx.h"
|
||||
|
||||
|
||||
/*static*/ CANDriver* CanTxMessage::s_device = nullptr;
|
||||
|
||||
/*static*/ void CanTxMessage::setDevice(CANDriver* device) {
|
||||
s_device = device;
|
||||
}
|
||||
|
||||
CanTxMessage::CanTxMessage(uint32_t eid) {
|
||||
m_frame.IDE = CAN_IDE_STD;
|
||||
m_frame.EID = eid;
|
||||
m_frame.RTR = CAN_RTR_DATA;
|
||||
m_frame.DLC = 8;
|
||||
memset(m_frame.data8, 0, sizeof(m_frame.data8));
|
||||
}
|
||||
|
||||
CanTxMessage::~CanTxMessage() {
|
||||
auto device = s_device;
|
||||
|
||||
if (!device) {
|
||||
warning(CUSTOM_ERR_CAN_CONFIGURATION, "CAN configuration issue");
|
||||
return;
|
||||
}
|
||||
|
||||
// 100 ms timeout
|
||||
canTransmit(device, CAN_ANY_MAILBOX, &m_frame, TIME_MS2I(100));
|
||||
}
|
||||
|
||||
uint8_t& CanTxMessage::operator[](size_t index) {
|
||||
return m_frame.data8[index];
|
||||
}
|
||||
|
||||
void CanTxMessage::setShortValue(uint16_t value, size_t offset) {
|
||||
m_frame.data8[offset] = value & 0xFF;
|
||||
m_frame.data8[offset + 1] = value >> 8;
|
||||
}
|
||||
|
||||
void CanTxMessage::setBit(size_t byteIdx, size_t bitIdx) {
|
||||
m_frame.data8[byteIdx] |= 1 << bitIdx;
|
||||
}
|
||||
|
||||
#endif // EFI_CAN_SUPPORT
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* @file can_msg_tx.h
|
||||
*
|
||||
* CAN message transmission
|
||||
*
|
||||
* @date Mar 13, 2020
|
||||
* @author Matthew Kennedy, (c) 2012-2020
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include "os_access.h"
|
||||
|
||||
/**
|
||||
* Represent a message to be transmitted over CAN.
|
||||
*
|
||||
* Usage:
|
||||
* * Create an instance of CanTxMessage
|
||||
* * Set any data you'd like to transmit either using the subscript operator to directly access bytes, or any of the helper functions.
|
||||
* * Upon destruction, the message is transmitted.
|
||||
*/
|
||||
class CanTxMessage
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a new CAN message, with the specified extended ID.
|
||||
*/
|
||||
CanTxMessage(uint32_t eid);
|
||||
|
||||
/**
|
||||
* Destruction of an instance of CanTxMessage will transmit the message over the wire.
|
||||
*/
|
||||
~CanTxMessage();
|
||||
|
||||
/**
|
||||
* Configures the device for all messages to transmit from.
|
||||
*/
|
||||
static void setDevice(CANDriver* device);
|
||||
|
||||
/**
|
||||
* @brief Read & write the raw underlying 8-byte buffer.
|
||||
*/
|
||||
uint8_t& operator[](size_t);
|
||||
|
||||
/**
|
||||
* @brief Write a 16-bit short value to the buffer. Note: this writes in big endian byte order.
|
||||
*/
|
||||
void setShortValue(uint16_t value, size_t offset);
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in the transmit buffer. Useful for single-bit flags.
|
||||
*/
|
||||
void setBit(size_t byteIdx, size_t bitIdx);
|
||||
|
||||
protected:
|
||||
CANTxFrame m_frame;
|
||||
|
||||
private:
|
||||
static CANDriver* s_device;
|
||||
};
|
||||
|
||||
/**
|
||||
* A CAN message based on a type, removing the need for manually flipping bits/bytes.
|
||||
*/
|
||||
template <typename TData>
|
||||
class CanTxTyped final : public CanTxMessage
|
||||
{
|
||||
static_assert(sizeof(TData) == sizeof(CANTxFrame::data8));
|
||||
|
||||
public:
|
||||
CanTxTyped(uint32_t eid) : CanTxMessage(eid) { }
|
||||
|
||||
/**
|
||||
* Access members of the templated type.
|
||||
*
|
||||
* So you can do:
|
||||
* CanTxTyped<MyType> d;
|
||||
* d->memberOfMyType = 23;
|
||||
*/
|
||||
TData* operator->() {
|
||||
return reinterpret_cast<TData*>(&m_frame.data8);
|
||||
}
|
||||
};
|
|
@ -16,4 +16,5 @@ HW_LAYER_DRIVERS = \
|
|||
|
||||
HW_LAYER_DRIVERS_CPP = \
|
||||
$(DRIVERS_DIR)/can/can_hw.cpp \
|
||||
$(DRIVERS_DIR)/can/can_msg_tx.cpp \
|
||||
|
||||
|
|
Loading…
Reference in New Issue