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