@@ -41,6 +41,30 @@ constexpr uint64_t generate_mask(uint8_t position, uint8_t length)
4141{
4242 return 0xFFFFFFFFFFFFFFFFull << (64 - length) >> (64 - (length + position));
4343}
44+
45+ template <typename SignalType>
46+ class ITypedCANSignal : public ICANSignal
47+ {
48+ public:
49+ SignalType &value_ref () { return signal_; }
50+
51+ void operator =(const SignalType &signal) { signal_ = signal; }
52+
53+ operator SignalType () const { return signal_; }
54+
55+ protected:
56+ SignalType signal_;
57+ };
58+
59+ // Needed so compiler knows these template classes exist
60+ template class ITypedCANSignal <uint8_t >;
61+ template class ITypedCANSignal <uint16_t >;
62+ template class ITypedCANSignal <uint32_t >;
63+ template class ITypedCANSignal <int8_t >;
64+ template class ITypedCANSignal <int16_t >;
65+ template class ITypedCANSignal <int32_t >;
66+ template class ITypedCANSignal <float >;
67+
4468static constexpr int kCANTemplateFloatDenominator {1 << 16 }; // 2^16
4569constexpr int CANTemplateConvertFloat (float value) { return value * kCANTemplateFloatDenominator ; }
4670constexpr float CANTemplateGetFloat (int value) { return static_cast <float >(value) / kCANTemplateFloatDenominator ; }
@@ -86,7 +110,7 @@ template <typename SignalType,
86110 bool unity_factor = factor == CANTemplateConvertFloat(1 )
87111 && offset == 0 > // unity_factor is used for increased precision on unity-factor 64-bit
88112 // signals by getting rid of floating point error
89- class CANSignal : public ICANSignal
113+ class CANSignal : public ITypedCANSignal <SignalType>
90114{
91115 using underlying_type = typename GetCANRawType<signed_raw>::type;
92116
@@ -100,25 +124,25 @@ class CANSignal : public ICANSignal
100124 {
101125 if (unity_factor)
102126 {
103- if (byte_order == ByteOrder::kLittleEndian )
127+ if (byte_order == ICANSignal:: ByteOrder::kLittleEndian )
104128 {
105- *buffer |= (static_cast <underlying_type>(signal_) << position) & mask;
129+ *buffer |= (static_cast <underlying_type>(this -> signal_ ) << position) & mask;
106130 }
107131 else
108132 {
109133 uint8_t temp_reversed_buffer[8 ]{0 };
110134 *reinterpret_cast <underlying_type *>(temp_reversed_buffer) |=
111- (static_cast <underlying_type>(signal_) << (64 - (position + length)));
135+ (static_cast <underlying_type>(this -> signal_ ) << (64 - (position + length)));
112136 std::reverse (std::begin (temp_reversed_buffer), std::end (temp_reversed_buffer));
113137 *buffer |= *reinterpret_cast <underlying_type *>(temp_reversed_buffer) & mask;
114138 }
115139 }
116140 else
117141 {
118- if (byte_order == ByteOrder::kLittleEndian )
142+ if (byte_order == ICANSignal:: ByteOrder::kLittleEndian )
119143 {
120144 *buffer |= (static_cast <underlying_type>(
121- ((signal_ - CANTemplateGetFloat (offset)) / CANTemplateGetFloat (factor)))
145+ ((this -> signal_ - CANTemplateGetFloat (offset)) / CANTemplateGetFloat (factor)))
122146 << position)
123147 & mask;
124148 }
@@ -127,7 +151,7 @@ class CANSignal : public ICANSignal
127151 uint8_t temp_reversed_buffer[8 ]{0 };
128152 *reinterpret_cast <underlying_type *>(temp_reversed_buffer) |=
129153 (static_cast <underlying_type>(
130- ((signal_ - CANTemplateGetFloat (offset)) / CANTemplateGetFloat (factor)))
154+ ((this -> signal_ - CANTemplateGetFloat (offset)) / CANTemplateGetFloat (factor)))
131155 << (64 - (position + length)));
132156 std::reverse (std::begin (temp_reversed_buffer), std::end (temp_reversed_buffer));
133157 *buffer |= *reinterpret_cast <underlying_type *>(temp_reversed_buffer) & mask;
@@ -139,29 +163,29 @@ class CANSignal : public ICANSignal
139163 {
140164 if (unity_factor)
141165 {
142- if (byte_order == ByteOrder::kLittleEndian )
166+ if (byte_order == ICANSignal:: ByteOrder::kLittleEndian )
143167 {
144168 uint8_t temp_buffer[8 ]{0 };
145169 *reinterpret_cast <underlying_type *>(temp_buffer) = *buffer & mask;
146- signal_ = static_cast <SignalType>(
170+ this -> signal_ = static_cast <SignalType>(
147171 (*reinterpret_cast <underlying_type *>(temp_buffer)) << (64 - (position + length)) >> (64 - length));
148172 }
149173 else
150174 {
151175 uint8_t temp_buffer[8 ]{0 };
152176 *reinterpret_cast <underlying_type *>(temp_buffer) = *buffer & mask;
153177 std::reverse (std::begin (temp_buffer), std::end (temp_buffer));
154- signal_ = static_cast <SignalType>((*reinterpret_cast <underlying_type *>(temp_buffer)) << position
155- >> (64 - length));
178+ this -> signal_ = static_cast <SignalType>((*reinterpret_cast <underlying_type *>(temp_buffer)) << position
179+ >> (64 - length));
156180 }
157181 }
158182 else
159183 {
160- if (byte_order == ByteOrder::kLittleEndian )
184+ if (byte_order == ICANSignal:: ByteOrder::kLittleEndian )
161185 {
162186 uint8_t temp_buffer[8 ]{0 };
163187 *reinterpret_cast <underlying_type *>(temp_buffer) = *buffer & mask;
164- signal_ = static_cast <SignalType>(
188+ this -> signal_ = static_cast <SignalType>(
165189 (((*reinterpret_cast <underlying_type *>(temp_buffer)) << (64 - (position + length))
166190 >> (64 - length))
167191 * CANTemplateGetFloat (factor))
@@ -172,22 +196,15 @@ class CANSignal : public ICANSignal
172196 uint8_t temp_buffer[8 ]{0 };
173197 *reinterpret_cast <underlying_type *>(temp_buffer) = *buffer & mask;
174198 std::reverse (std::begin (temp_buffer), std::end (temp_buffer));
175- signal_ = static_cast <SignalType>(
199+ this -> signal_ = static_cast <SignalType>(
176200 (((*reinterpret_cast <underlying_type *>(temp_buffer)) << position >> (64 - length))
177201 * CANTemplateGetFloat (factor))
178202 + CANTemplateGetFloat (offset));
179203 }
180204 }
181205 }
182206
183- SignalType &value_ref () { return signal_; }
184-
185- void operator =(const SignalType &signal) { signal_ = signal; }
186-
187- operator SignalType () const { return signal_; }
188-
189- private:
190- SignalType signal_;
207+ void operator =(const SignalType &signal) { ITypedCANSignal<SignalType>::operator =(signal); }
191208};
192209
193210// Macros for making signed and unsigned little-endian CAN signals
0 commit comments