mirror of https://github.com/rusefi/wideband.git
77 lines
1.8 KiB
C++
77 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
#include "hal.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.
|
|
*/
|
|
explicit CanTxMessage(uint32_t eid, uint8_t dlc = 8, bool isExtended = false);
|
|
|
|
/**
|
|
* Destruction of an instance of CanTxMessage will transmit the message over the wire.
|
|
*/
|
|
~CanTxMessage();
|
|
|
|
/**
|
|
* @brief Read & write the raw underlying 8-byte buffer.
|
|
*/
|
|
uint8_t& operator[](size_t);
|
|
|
|
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:
|
|
explicit 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);
|
|
}
|
|
|
|
TData& get()
|
|
{
|
|
return *reinterpret_cast<TData*>(&m_frame.data8);
|
|
}
|
|
};
|
|
|
|
template <typename TData>
|
|
void transmitStruct(uint32_t eid)
|
|
{
|
|
CanTxTyped<TData> frame(eid);
|
|
// Destruction of an instance of CanTxMessage will transmit the message over the wire.
|
|
// see CanTxMessage::~CanTxMessage()
|
|
populateFrame(frame.get());
|
|
}
|