2020-03-18 19:07:41 -07:00
|
|
|
/**
|
|
|
|
* @file can_msg_tx.h
|
|
|
|
*
|
|
|
|
* CAN message transmission
|
2024-02-26 11:51:01 -08:00
|
|
|
*
|
2020-03-18 19:07:41 -07:00
|
|
|
* @date Mar 13, 2020
|
|
|
|
* @author Matthew Kennedy, (c) 2012-2020
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <cstddef>
|
|
|
|
|
2022-09-18 17:44:00 -07:00
|
|
|
#include "can_category.h"
|
2021-12-08 09:01:28 -08:00
|
|
|
#include "can.h"
|
2020-03-18 19:07:41 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represent a message to be transmitted over CAN.
|
2024-02-26 11:51:01 -08:00
|
|
|
*
|
2020-03-18 19:07:41 -07:00
|
|
|
* 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.
|
|
|
|
*/
|
2023-02-20 08:29:25 -08:00
|
|
|
explicit CanTxMessage(CanCategory category, uint32_t eid, uint8_t dlc = 8, size_t bus = 0, bool isExtended = false);
|
2020-03-18 19:07:41 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Destruction of an instance of CanTxMessage will transmit the message over the wire.
|
|
|
|
*/
|
|
|
|
~CanTxMessage();
|
|
|
|
|
2022-09-18 17:44:00 -07:00
|
|
|
CanCategory category;
|
|
|
|
|
2021-02-05 20:57:28 -08:00
|
|
|
#if EFI_CAN_SUPPORT
|
2020-03-18 19:07:41 -07:00
|
|
|
/**
|
|
|
|
* Configures the device for all messages to transmit from.
|
|
|
|
*/
|
2021-12-20 21:48:13 -08:00
|
|
|
static void setDevice(CANDriver* device1, CANDriver* device2);
|
2021-02-05 20:57:28 -08:00
|
|
|
#endif // EFI_CAN_SUPPORT
|
2021-12-20 22:10:37 -08:00
|
|
|
|
|
|
|
size_t busIndex = 0;
|
|
|
|
|
2020-03-18 19:07:41 -07:00
|
|
|
/**
|
|
|
|
* @brief Read & write the raw underlying 8-byte buffer.
|
|
|
|
*/
|
|
|
|
uint8_t& operator[](size_t);
|
|
|
|
|
|
|
|
/**
|
2024-02-26 11:51:01 -08:00
|
|
|
* @brief Write a 16-bit short value to the buffer. Note: this writes in little endian byte order.
|
2020-03-18 19:07:41 -07:00
|
|
|
*/
|
|
|
|
void setShortValue(uint16_t value, size_t offset);
|
|
|
|
|
2024-02-26 15:02:46 -08:00
|
|
|
// Same as above but big endian
|
|
|
|
void setShortValueMsb(uint16_t value, size_t offset);
|
|
|
|
|
2020-03-18 19:07:41 -07:00
|
|
|
/**
|
|
|
|
* @brief Set a single bit in the transmit buffer. Useful for single-bit flags.
|
|
|
|
*/
|
|
|
|
void setBit(size_t byteIdx, size_t bitIdx);
|
|
|
|
|
2021-07-16 11:06:26 -07:00
|
|
|
void setDlc(uint8_t dlc);
|
|
|
|
|
2023-02-20 08:29:25 -08:00
|
|
|
void setBus(size_t bus);
|
|
|
|
|
2023-09-13 21:12:56 -07:00
|
|
|
#if HAS_CAN_FRAME
|
2021-12-08 09:01:28 -08:00
|
|
|
const CANTxFrame *getFrame() const {
|
|
|
|
return &m_frame;
|
|
|
|
}
|
2024-04-02 21:06:42 -07:00
|
|
|
|
|
|
|
void setArray(uint8_t *data, size_t len) {
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
m_frame.data8[i] = data[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 13:24:54 -08:00
|
|
|
#endif // HAL_USE_CAN || EFI_UNIT_TEST
|
2021-12-08 09:01:28 -08:00
|
|
|
|
2020-03-18 19:07:41 -07:00
|
|
|
protected:
|
2023-09-13 21:12:56 -07:00
|
|
|
#if HAS_CAN_FRAME
|
2020-03-18 19:07:41 -07:00
|
|
|
CANTxFrame m_frame;
|
2021-12-08 13:24:54 -08:00
|
|
|
#endif // HAL_USE_CAN || EFI_UNIT_TEST
|
2020-03-18 19:07:41 -07:00
|
|
|
|
|
|
|
private:
|
2021-02-05 20:57:28 -08:00
|
|
|
#if EFI_CAN_SUPPORT
|
2021-12-20 21:48:13 -08:00
|
|
|
static CANDriver* s_devices[2];
|
2021-02-05 20:57:28 -08:00
|
|
|
#endif // EFI_CAN_SUPPORT
|
2020-03-18 19:07:41 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A CAN message based on a type, removing the need for manually flipping bits/bytes.
|
|
|
|
*/
|
|
|
|
template <typename TData>
|
|
|
|
class CanTxTyped final : public CanTxMessage
|
|
|
|
{
|
2021-02-05 20:57:28 -08:00
|
|
|
#if EFI_CAN_SUPPORT
|
2021-03-09 15:54:01 -08:00
|
|
|
static_assert(sizeof(TData) <= sizeof(CANTxFrame::data8));
|
2021-02-05 20:57:28 -08:00
|
|
|
#endif // EFI_CAN_SUPPORT
|
2020-03-18 19:07:41 -07:00
|
|
|
|
|
|
|
public:
|
2024-02-05 00:05:32 -08:00
|
|
|
explicit CanTxTyped(CanCategory p_category, uint32_t p_id, bool p_isExtended, size_t canChannel) : CanTxMessage(p_category, p_id, sizeof(TData), canChannel, p_isExtended) { }
|
2020-03-18 19:07:41 -07:00
|
|
|
|
2021-02-05 20:57:28 -08:00
|
|
|
#if EFI_CAN_SUPPORT
|
2020-03-18 19:07:41 -07:00
|
|
|
/**
|
2024-02-26 11:51:01 -08:00
|
|
|
* Access members of the templated type.
|
|
|
|
*
|
2020-03-18 19:07:41 -07:00
|
|
|
* So you can do:
|
|
|
|
* CanTxTyped<MyType> d;
|
|
|
|
* d->memberOfMyType = 23;
|
|
|
|
*/
|
|
|
|
TData* operator->() {
|
|
|
|
return reinterpret_cast<TData*>(&m_frame.data8);
|
|
|
|
}
|
2020-03-19 14:58:46 -07:00
|
|
|
|
|
|
|
TData& get() {
|
|
|
|
return *reinterpret_cast<TData*>(&m_frame.data8);
|
|
|
|
}
|
2021-02-05 20:57:28 -08:00
|
|
|
#endif // EFI_CAN_SUPPORT
|
2020-03-18 19:07:41 -07:00
|
|
|
};
|
2020-03-19 14:58:46 -07:00
|
|
|
|
|
|
|
template <typename TData>
|
2023-10-30 18:42:52 -07:00
|
|
|
void transmitStruct(CanCategory category, uint32_t id, bool isExtended, bool canChannel)
|
2020-03-19 14:58:46 -07:00
|
|
|
{
|
2023-10-30 18:42:52 -07:00
|
|
|
CanTxTyped<TData> frame(category, id, isExtended, canChannel);
|
2020-03-31 17:57:52 -07:00
|
|
|
// Destruction of an instance of CanTxMessage will transmit the message over the wire.
|
|
|
|
// see CanTxMessage::~CanTxMessage()
|
2020-03-19 14:58:46 -07:00
|
|
|
populateFrame(frame.get());
|
|
|
|
}
|