M5Unit-RS485 0.0.1 git rev:d5ba212
Loading...
Searching...
No Matches
unit_SP485.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_RS485_UNIT_SP485_HPP
11#define M5_UNIT_RS485_UNIT_SP485_HPP
12
13#include <M5UnitComponent.hpp>
14#include <m5_utility/stl/byteswap.hpp>
15#include <m5_utility/stl/endianness.hpp>
16#include <type_traits>
17
18class HardwareSerial;
19
20namespace m5 {
21namespace unit {
22
27class UnitSP485 : public Component {
28 M5_UNIT_COMPONENT_HPP_BUILDER(UnitSP485, 0x00 /*UART*/);
29
30public:
32 struct ISerial {
33 virtual ~ISerial() = default;
34 virtual int available() = 0;
35 virtual int availableForWrite() = 0;
36 virtual int peek() = 0;
37 virtual int read() = 0;
38 virtual size_t read(uint8_t *buf, const size_t len) = 0;
39 virtual size_t readBytes(uint8_t *buf, const size_t len) = 0;
40 virtual void flush() = 0;
41 virtual void flush(const bool txOnly) = 0;
42 virtual size_t write(const uint8_t *buf, const size_t len) = 0;
43 virtual size_t write(uint8_t b) = 0;
44 virtual uint32_t baudRate() const = 0;
45 };
47
51 UnitSP485();
53 virtual ~UnitSP485() = default;
54
59 virtual bool begin() override;
60
65 struct config_t {
66 bool flushRX{true};
67 };
68
71
76 {
77 return _cfg;
78 }
83 inline void config(const config_t &cfg)
84 {
85 _cfg = cfg;
86 }
88
93 inline operator bool() const
94 {
95 return isRegistered();
96 }
101 inline int available()
102 {
103 return _serial->available();
104 }
109 inline int availableForWrite()
110 {
111 return _serial->availableForWrite();
112 }
117 inline int peek()
118 {
119 return _serial->peek();
120 }
125 inline int read()
126 {
127 return _serial->read();
128 }
135 inline size_t read(uint8_t *buffer, const size_t size)
136 {
137 return _serial->read(buffer, size);
138 }
145 inline size_t read(char *buffer, const size_t size)
146 {
147 return read(reinterpret_cast<uint8_t *>(buffer), size);
148 }
155 size_t readBytes(uint8_t *buffer, const size_t length)
156 {
157 return _serial->readBytes(buffer, length);
158 }
165 inline size_t readBytes(char *buffer, const size_t length)
166 {
167 return readBytes(reinterpret_cast<uint8_t *>(buffer), length);
168 }
172 inline void flush()
173 {
174 _serial->flush();
175 }
180 inline void flush(const bool txOnly)
181 {
182 _serial->flush(txOnly);
183 }
191 size_t write(const uint8_t d, const bool flush = true);
199 size_t write(const uint8_t *buffer, const size_t size, const bool flush = true);
207 size_t write(const char *buffer, const size_t size, const bool flush = true);
214 size_t write(const char *s, const bool flush = true);
216
219
226 template <typename T, bool LittleEndian = true>
227 bool readValue(T &value)
228 {
229 static_assert(std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value,
230 "readValue requires trivially copyable, standard-layout types only");
231 value = T{};
232 uint8_t buf[sizeof(T)]{};
233 size_t got = _serial->readBytes(buf, sizeof(T));
234 if (got != sizeof(T)) {
235 return false;
236 }
237 std::memcpy(&value, buf, sizeof(T));
238 if (LittleEndian != m5::endian::little) {
239 value = byteswap_if_needed(value);
240 }
241 return true;
242 }
250 template <typename T, bool LittleEndian = true>
251 bool writeValue(const T value)
252 {
253 static_assert(std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value,
254 "writeValue requires trivially copyable, standard-layout types only");
255 T tmp = value;
256 if (LittleEndian != m5::endian::little) {
257 tmp = byteswap_if_needed(tmp);
258 }
259 uint8_t buf[sizeof(T)]{};
260 std::memcpy(buf, &tmp, sizeof(T));
261 return write(buf, sizeof(T), true) == sizeof(T);
262 }
264
265protected:
266 inline ISerial *iserial()
267 {
268 return _serial.get();
269 }
270
271 template <typename T>
272 static T byteswap_if_needed(T v)
273 {
274 return byteswap_if_needed_impl(v, std::integral_constant < bool,
275 std::is_integral<T>::value || std::is_enum<T>::value > {});
276 }
277
278 template <typename T>
279 static T byteswap_if_needed_impl(T v, std::true_type)
280 {
281 return m5::stl::byteswap(v);
282 }
283
284 template <typename T>
285 static T byteswap_if_needed_impl(T v, std::false_type)
286 {
287 return v;
288 }
289
290private:
291 std::unique_ptr<ISerial> _serial{};
292 config_t _cfg{};
293};
294
295} // namespace unit
296} // namespace m5
297#endif
RS-485 unit using SP485 transceiver.
Definition unit_SP485.hpp:27
virtual ~UnitSP485()=default
Destructor.
virtual bool begin() override
Begin using the registered UART adapter.
Definition unit_SP485.cpp:130
size_t readBytes(uint8_t *buffer, const size_t length)
Reads bytes with timeout defined by underlying Serial.
Definition unit_SP485.hpp:155
void flush(const bool txOnly)
Flushes the serial port.
Definition unit_SP485.hpp:180
int availableForWrite()
Returns the number of bytes that can be written without blocking.
Definition unit_SP485.hpp:109
size_t readBytes(char *buffer, const size_t length)
Reads bytes with timeout defined by underlying Serial.
Definition unit_SP485.hpp:165
size_t write(const uint8_t d, const bool flush=true)
Writes one byte.
Definition unit_SP485.cpp:149
bool writeValue(const T value)
Write the any number value.
Definition unit_SP485.hpp:251
void flush()
Flushes the serial port.
Definition unit_SP485.hpp:172
int read()
Reads one byte.
Definition unit_SP485.hpp:125
size_t read(uint8_t *buffer, const size_t size)
Reads up to size bytes into buffer.
Definition unit_SP485.hpp:135
UnitSP485()
Constructor.
Definition unit_SP485.cpp:125
config_t config()
Gets the configuration.
Definition unit_SP485.hpp:75
int peek()
Peeks the next incoming byte without removing it.
Definition unit_SP485.hpp:117
int available()
Returns the number of available bytes to read.
Definition unit_SP485.hpp:101
bool readValue(T &value)
Read the any number value.
Definition unit_SP485.hpp:227
void config(const config_t &cfg)
Sets the configuration.
Definition unit_SP485.hpp:83
size_t read(char *buffer, const size_t size)
Reads up to size bytes into buffer.
Definition unit_SP485.hpp:145
Top level namespace of M5stack.
Unit-related namespace.
Settings for begin.
Definition unit_SP485.hpp:65
bool flushRX
Flush RX buffer on begin?
Definition unit_SP485.hpp:66