rusEFI
The most advanced open source ECU
can_msg_tx.h
Go to the documentation of this file.
1 /**
2  * @file can_msg_tx.h
3  *
4  * CAN message transmission
5  *
6  * @date Mar 13, 2020
7  * @author Matthew Kennedy, (c) 2012-2020
8  */
9 
10 #pragma once
11 
12 #include <cstdint>
13 #include <cstddef>
14 
15 #include "can_category.h"
16 #include "can.h"
17 
18 /**
19  * Represent a message to be transmitted over CAN.
20  *
21  * Usage:
22  * * Create an instance of CanTxMessage
23  * * Set any data you'd like to transmit either using the subscript operator to directly access bytes, or any of the helper functions.
24  * * Upon destruction, the message is transmitted.
25  */
27 {
28 public:
29  /**
30  * Create a new CAN message, with the specified extended ID.
31  */
32  explicit CanTxMessage(CanCategory category, uint32_t eid, uint8_t dlc = 8, size_t bus = 0, bool isExtended = false);
33 
34  /**
35  * Destruction of an instance of CanTxMessage will transmit the message over the wire.
36  */
37  ~CanTxMessage();
38 
40 
41 #if EFI_CAN_SUPPORT
42  /**
43  * Configures the device for all messages to transmit from.
44  */
45  static void setDevice(CANDriver* device1, CANDriver* device2);
46 #endif // EFI_CAN_SUPPORT
47 
48  size_t busIndex = 0;
49 
50  /**
51  * @brief Read & write the raw underlying 8-byte buffer.
52  */
53  uint8_t& operator[](size_t);
54 
55  /**
56  * @brief Write a 16-bit short value to the buffer. Note: this writes in little endian byte order.
57  */
58  void setShortValue(uint16_t value, size_t offset);
59 
60  /**
61  Same as above but big endian
62  * for instance DBC 8|16@0
63  */
64  void setShortValueMsb(uint16_t value, size_t offset);
65 
66  /**
67  * @brief Set a single bit in the transmit buffer. Useful for single-bit flags.
68  */
69  void setBit(size_t byteIdx, size_t bitIdx);
70 
71  void setDlc(uint8_t dlc);
72 
73  void setBus(size_t bus);
74 
75 #if HAS_CAN_FRAME
76  const CANTxFrame *getFrame() const {
77  return &m_frame;
78  }
79 
80 void setArray(uint8_t *data, size_t len) {
81  for (size_t i = 0; i < len; i++) {
82  m_frame.data8[i] = data[i];
83  }
84 }
85 
86 #endif // HAL_USE_CAN || EFI_UNIT_TEST
87 
88 protected:
89 #if HAS_CAN_FRAME
91 #endif // HAL_USE_CAN || EFI_UNIT_TEST
92 
93 private:
94 #if EFI_CAN_SUPPORT
95  static CANDriver* s_devices[2];
96 #endif // EFI_CAN_SUPPORT
97 };
98 
99 /**
100  * A CAN message based on a type, removing the need for manually flipping bits/bytes.
101  */
102 template <typename TData>
103 class CanTxTyped final : public CanTxMessage
104 {
105 #if EFI_CAN_SUPPORT
106  static_assert(sizeof(TData) <= sizeof(CANTxFrame::data8));
107 #endif // EFI_CAN_SUPPORT
108 
109 public:
110  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) { }
111 
112 #if EFI_CAN_SUPPORT
113  /**
114  * Access members of the templated type.
115  *
116  * So you can do:
117  * CanTxTyped<MyType> d;
118  * d->memberOfMyType = 23;
119  */
120  TData* operator->() {
121  return reinterpret_cast<TData*>(&m_frame.data8);
122  }
123 
124  TData& get() {
125  return *reinterpret_cast<TData*>(&m_frame.data8);
126  }
127 #endif // EFI_CAN_SUPPORT
128 };
129 
130 template <typename TData>
131 void transmitStruct(CanCategory category, uint32_t id, bool isExtended, bool canChannel)
132 {
133  CanTxTyped<TData> frame(category, id, isExtended, canChannel);
134  // Destruction of an instance of CanTxMessage will transmit the message over the wire.
135  // see CanTxMessage::~CanTxMessage()
136  populateFrame(frame.get());
137 }
CanCategory
Definition: can_category.h:7
static void populateFrame(Aim5f0 &msg)
Definition: can_dash.cpp:1095
void transmitStruct(CanCategory category, uint32_t id, bool isExtended, bool canChannel)
Definition: can_msg_tx.h:131
const CANTxFrame * getFrame() const
Definition: can_msg_tx.h:76
uint8_t & operator[](size_t)
Read & write the raw underlying 8-byte buffer.
Definition: can_msg_tx.cpp:132
static void setDevice(CANDriver *device1, CANDriver *device2)
Definition: can_msg_tx.cpp:25
void setBit(size_t byteIdx, size_t bitIdx)
Set a single bit in the transmit buffer. Useful for single-bit flags.
Definition: can_msg_tx.cpp:128
void setShortValueMsb(uint16_t value, size_t offset)
Definition: can_msg_tx.cpp:123
void setBus(size_t bus)
Definition: can_msg_tx.cpp:112
static CANDriver * s_devices[2]
Definition: can_msg_tx.h:95
CanTxMessage(CanCategory category, uint32_t eid, uint8_t dlc=8, size_t bus=0, bool isExtended=false)
Definition: can_msg_tx.cpp:31
void setShortValue(uint16_t value, size_t offset)
Write a 16-bit short value to the buffer. Note: this writes in little endian byte order.
Definition: can_msg_tx.cpp:117
void setDlc(uint8_t dlc)
Definition: can_msg_tx.cpp:108
void setArray(uint8_t *data, size_t len)
Definition: can_msg_tx.h:80
size_t busIndex
Definition: can_msg_tx.h:48
CanCategory category
Definition: can_msg_tx.h:39
CANTxFrame m_frame
Definition: can_msg_tx.h:90
CanTxTyped(CanCategory p_category, uint32_t p_id, bool p_isExtended, size_t canChannel)
Definition: can_msg_tx.h:110
TData * operator->()
Definition: can_msg_tx.h:120
TData & get()
Definition: can_msg_tx.h:124
uint8_t data8[8]
Frame data.
Definition: can_mocks.h:27
static CanTsChannel canChannel