rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
mlg_field.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <cstring>
5
6#include <rusefi/scaled_channel.h>
7
8#include "writer.h"
9#include "mlg_types.h"
10
11// For unit tests we are manipulating with storage in runtime so consteval is not possible.
12// In prod builds we have engine and configs as global instances so all addresses to read data from
13// must be known compile-time. If consteval fails then some runtime logic made its way into LogField and that moves
14// LogField instance into RAM which is correct from code perspective but incorrect intent-wise and consume code and RAM
15// for no real reason.
16#if defined(EFI_UNIT_TEST) && EFI_UNIT_TEST
17#define LOG_FIELD_CONSTNESS_SPECIFIER_METHODS constexpr
18#define LOG_FIELD_CONSTNESS_SPECIFIER_STORAGE const
19#else
20#define LOG_FIELD_CONSTNESS_SPECIFIER_METHODS consteval
21#define LOG_FIELD_CONSTNESS_SPECIFIER_STORAGE const constinit
22#endif
23
24namespace MLG::Entries {
25using namespace MLG;
26
27class Field {
28public:
29 // Scaled channels, memcpys data directly and describes format in header
30 template <typename TValue, int TMult, int TDiv>
31 LOG_FIELD_CONSTNESS_SPECIFIER_METHODS Field(const scaled_channel<TValue, TMult, TDiv>& toRead,
32 const char* name, const char* units, int8_t digits, const char* category = "none")
33 : m_multiplier(float(TDiv) / TMult)
34 , m_addr(toRead.getFirstByteAddr())
35 , m_type_id(static_cast<std::underlying_type_t<Types::Field::Scalar>>(Types::Field::resolveBuiltInNumberType<TValue>()))
36 , m_digits(digits)
37 , m_size(Types::Field::sizeForType<Types::Field::resolveBuiltInNumberType<TValue>()>())
38 , m_name(name)
39 , m_units(units)
40 , m_category(category)
41 , m_isBitField(false)
43 , m_bitNumber(0)
44 {
45 }
46
47 // Non-scaled channel, works for plain arithmetic types (int, float, uint8_t, etc)
48 template <typename TValue, typename = typename std::enable_if<std::is_arithmetic_v<TValue>>::type>
49 LOG_FIELD_CONSTNESS_SPECIFIER_METHODS Field(TValue& toRead,
50 const char* name, const char* units, int8_t digits, const char* category = "none")
51 : m_multiplier(1)
52 , m_addr(&toRead)
53 , m_type_id(static_cast<std::underlying_type_t<Types::Field::Scalar>>(Types::Field::resolveBuiltInNumberType<TValue>()))
54 , m_digits(digits)
55 , m_size(Types::Field::sizeForType<Types::Field::resolveBuiltInNumberType<TValue>()>())
56 , m_name(name)
57 , m_units(units)
58 , m_category(category)
59 , m_isBitField(false)
61 , m_bitNumber(0)
62 {
63 }
64
65 // Bit channel
66 template <typename TValue>
67 LOG_FIELD_CONSTNESS_SPECIFIER_METHODS Field(
68 TValue& toRead,
69 const uint32_t bitsBlockOffset,
70 const uint8_t bitNumber,
71 const char* name,
72 const char* units,
73 const char* category = "none"
74 ): m_multiplier(1)
75 , m_addr(&toRead)
76 , m_type_id(static_cast<std::underlying_type_t<Types::Field::Scalar>>(Types::Field::Scalar::U08))
77 , m_digits(0)
78 , m_size(1)
79 , m_name(name)
80 , m_units(units)
81 , m_category(category)
82 , m_isBitField(true)
83 , m_bitsBlockOffset(bitsBlockOffset)
84 , m_bitNumber(bitNumber)
85 {
86 }
87
88 constexpr size_t getSize() const { return m_size; }
89 constexpr const void* getAddr() const { return m_addr; }
90
91 // Write the header data describing this field.
92 // Returns the number of bytes written.
93 size_t writeHeader(Writer& outBuffer) const {
95
96 // Offset 0, length 1 = type
97 buffer[0] = static_cast<char>(m_type_id);
98
99 // Offset 1, length 34 = name
100 strncpy(&buffer[1], m_name, 34);
101
102 // Offset 35, length 10 = units
103 strncpy(&buffer[35], m_units, 10);
104
105 // Offset 45, length 1 = Display style
106 // value 0 -> floating point number
107 buffer[45] = 0;
108
109 // Offset 46, length 4 = Scale
111
112 // Offset 50, length 4 = shift before scaling (always 0)
113 copyFloat(buffer + 50, 0);
114
115 // Offset 54, size 1 = digits to display (signed int)
116 buffer[54] = m_digits;
117
118 // Offset 55, (optional) category string
119 if (m_category) {
120 size_t categoryLength = strlen(m_category);
121 size_t lengthAfterCategory = 34 - categoryLength;
122 memcpy(&buffer[55], m_category, categoryLength);
123 memset(&buffer[55] + categoryLength, 0, lengthAfterCategory);
124 } else {
125 memset(&buffer[55], 0, 34);
126 }
127
128 // Total size = 89
130
132 }
133
134 // Write the field's data to the buffer.
135 // Returns the number of bytes written.
136 size_t writeData(char* buffer, void *offset) const {
137 if (m_isBitField) {
138 const char* const bitsBlockAddr = static_cast<const char*>(m_addr) + m_bitsBlockOffset;
139 const char* const byteWithBitAddr = bitsBlockAddr + m_bitNumber / 8;
140 unsigned char byteWithBit = 0;
141 memcpy_swapend(&byteWithBit, byteWithBitAddr, m_size, offset);
142 const uint8_t bitNumberInByte = m_bitNumber % 8;
143 buffer[0] = static_cast<char>(static_cast<bool>(byteWithBit & (1 << bitNumberInByte)));
144 } else {
146 }
147
148 return m_size;
149 }
150
151private:
152
153 static void memcpy_swapend(void* dest, const void* src, size_t const size, void *offset) {
154 const char* src2 = reinterpret_cast<const char*>(src);
155 char* dest2 = reinterpret_cast<char*>(dest);
156 for (size_t i = 0; i < size; i++) {
157 // Endian swap - copy the end to the beginning
158 dest2[i] = src2[size - 1 - i + (uint64_t)offset];
159 }
160 }
161
162 static void copyFloat(char* buffer, float value) {
163 memcpy_swapend(buffer, &value, sizeof(float), nullptr);
164 }
165
166 const float m_multiplier;
167 const void* const m_addr;
168 const uint8_t m_type_id;
169 const int8_t m_digits;
170 const uint8_t m_size;
171
172 const char* const m_name;
173 const char* const m_units;
174 const char* const m_category;
175
176 const bool m_isBitField;
177 const uint32_t m_bitsBlockOffset; // only for bit log fields
178 const uint8_t m_bitNumber; // only for bit log fields
179};
180}
const bool m_isBitField
Definition mlg_field.h:176
constexpr const void * getAddr() const
Definition mlg_field.h:89
LOG_FIELD_CONSTNESS_SPECIFIER_METHODS Field(const scaled_channel< TValue, TMult, TDiv > &toRead, const char *name, const char *units, int8_t digits, const char *category="none")
Definition mlg_field.h:31
LOG_FIELD_CONSTNESS_SPECIFIER_METHODS Field(TValue &toRead, const uint32_t bitsBlockOffset, const uint8_t bitNumber, const char *name, const char *units, const char *category="none")
Definition mlg_field.h:67
const void *const m_addr
Definition mlg_field.h:167
size_t writeHeader(Writer &outBuffer) const
Definition mlg_field.h:93
const uint8_t m_type_id
Definition mlg_field.h:168
const char *const m_category
Definition mlg_field.h:174
const char *const m_units
Definition mlg_field.h:173
const uint8_t m_size
Definition mlg_field.h:170
static void copyFloat(char *buffer, float value)
Definition mlg_field.h:162
size_t writeData(char *buffer, void *offset) const
Definition mlg_field.h:136
const uint32_t m_bitsBlockOffset
Definition mlg_field.h:177
LOG_FIELD_CONSTNESS_SPECIFIER_METHODS Field(TValue &toRead, const char *name, const char *units, int8_t digits, const char *category="none")
Definition mlg_field.h:49
const uint8_t m_bitNumber
Definition mlg_field.h:178
constexpr size_t getSize() const
Definition mlg_field.h:88
const char *const m_name
Definition mlg_field.h:172
const float m_multiplier
Definition mlg_field.h:166
const int8_t m_digits
Definition mlg_field.h:169
static void memcpy_swapend(void *dest, const void *src, size_t const size, void *offset)
Definition mlg_field.h:153
constexpr size_t DescriptorSize
Definition mlg_types.h:71
Definition writer.h:9
virtual size_t write(const char *buffer, size_t count)=0
composite packet size
static BigBufferHandle buffer
uint16_t offset
Definition tunerstudio.h:0