idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
onewire.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
21#include <idfxx/error>
22#include <idfxx/gpio>
23
24#include <cstdint>
25#include <memory>
26#include <mutex>
27#include <span>
28#include <string>
29#include <vector>
30
35namespace idfxx::onewire {
36
47class address {
48public:
50 constexpr address() = default;
51
56 constexpr explicit address(uint64_t raw)
57 : _raw(raw) {}
58
67 [[nodiscard]] static constexpr address any() { return address{}; }
68
77 [[nodiscard]] static constexpr address none() { return address{0xFFFFFFFFFFFFFFFF}; }
78
83 [[nodiscard]] constexpr uint64_t raw() const { return _raw; }
84
93 [[nodiscard]] constexpr uint8_t family() const { return static_cast<uint8_t>(_raw & 0xFF); }
94
96 [[nodiscard]] constexpr bool operator==(const address&) const noexcept = default;
97
99 [[nodiscard]] constexpr auto operator<=>(const address&) const noexcept = default;
100
101private:
102 uint64_t _raw = 0;
103};
104
105class bus;
106
107// -- CRC utilities -----------------------------------------------------------
108
118[[nodiscard]] uint8_t crc8(std::span<const uint8_t> data);
119
133[[nodiscard]] uint16_t crc16(std::span<const uint8_t> data, uint16_t crc_iv = 0);
134
144[[nodiscard]] bool
145check_crc16(std::span<const uint8_t> data, std::span<const uint8_t, 2> inverted_crc, uint16_t crc_iv = 0);
146
147// -- bus ---------------------------------------------------------------------
148
170class bus {
171public:
172#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
180 [[nodiscard]] explicit bus(gpio pin);
181#endif
182
191
192 ~bus() = default;
193
194 bus(const bus&) = delete;
195 bus& operator=(const bus&) = delete;
196 bus(bus&& other) noexcept = default;
197 bus& operator=(bus&& other) noexcept = default;
198
200 void lock() const {
201 if (!_mux) {
202 return;
203 }
204 _mux->lock();
205 }
206
209 if (!_mux) {
210 return false;
211 }
212 return _mux->try_lock();
213 }
214
216 void unlock() const {
217 if (!_mux) {
218 return;
219 }
220 _mux->unlock();
221 }
222
224 [[nodiscard]] gpio pin() const noexcept { return _pin; }
225
226 // -- Bus reset -----------------------------------------------------------
227
236 [[nodiscard]] bool reset();
237
238 // -- ROM commands --------------------------------------------------------
239
240#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
251 void select(address addr) { unwrap(try_select(addr)); }
252
263#endif
264
275
285
286 // -- Write operations ----------------------------------------------------
287
288#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
296 void write(uint8_t value) { unwrap(try_write(value)); }
297
305 void write(std::span<const uint8_t> data) { unwrap(try_write(data)); }
306#endif
307
315
322 [[nodiscard]] result<void> try_write(std::span<const uint8_t> data);
323
324 // -- Read operations -----------------------------------------------------
325
326#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
334 [[nodiscard]] uint8_t read() { return unwrap(try_read()); }
335
343 void read(std::span<uint8_t> buf) { unwrap(try_read(buf)); }
344#endif
345
352
359 [[nodiscard]] result<void> try_read(std::span<uint8_t> buf);
360
361 // -- Parasitic power -----------------------------------------------------
362
363#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
373 void power() { unwrap(try_power()); }
374#endif
375
385
393
394 // -- Device search -------------------------------------------------------
395
396#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
405 [[nodiscard]] std::vector<address> search(size_t max_devices = 8) { return unwrap(try_search(max_devices)); }
406
416 [[nodiscard]] std::vector<address> search(uint8_t family_code, size_t max_devices = 8) {
418 }
419#endif
420
428
438
439private:
441 struct validated {};
443 : _pin(pin)
444 , _mux(std::make_unique<std::recursive_mutex>()) {}
447 gpio _pin;
448 mutable std::unique_ptr<std::recursive_mutex> _mux;
449};
450
// end of idfxx_onewire
452
453} // namespace idfxx::onewire
454
455namespace idfxx {
456
466[[nodiscard]] inline std::string to_string(onewire::address addr) {
467 if (addr == onewire::address::any()) {
468 return "ONEWIRE_ANY";
469 }
470 if (addr == onewire::address::none()) {
471 return "ONEWIRE_NONE";
472 }
473 static constexpr char hex[] = "0123456789ABCDEF";
474 std::string result;
475 result.reserve(23);
476 auto raw = addr.raw();
477 for (int i = 0; i < 8; ++i) {
478 if (i > 0) {
479 result += ':';
480 }
481 auto byte = static_cast<uint8_t>((raw >> (i * 8)) & 0xFF);
482 result += hex[byte >> 4];
483 result += hex[byte & 0xF];
484 }
485 return result;
486}
487
488} // namespace idfxx
489
490#include "sdkconfig.h"
491#ifdef CONFIG_IDFXX_STD_FORMAT
493#include <algorithm>
494#include <format>
495namespace std {
496template<>
497struct formatter<idfxx::onewire::address> {
498 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
499
500 template<typename FormatContext>
501 auto format(idfxx::onewire::address addr, FormatContext& ctx) const {
502 auto s = idfxx::to_string(addr);
503 return std::copy(s.begin(), s.end(), ctx.out());
504 }
505};
506} // namespace std
508#endif // CONFIG_IDFXX_STD_FORMAT
A GPIO pin.
Definition gpio.hpp:61
1-Wire device address.
Definition onewire.hpp:47
constexpr address()=default
Constructs an address with value 0 (equivalent to any()).
constexpr uint8_t family() const
Extracts the family code from the address.
Definition onewire.hpp:93
constexpr uint64_t raw() const
Returns the underlying 64-bit ROM address.
Definition onewire.hpp:83
constexpr bool operator==(const address &) const noexcept=default
Compares two addresses for equality.
constexpr auto operator<=>(const address &) const noexcept=default
Default three-way comparison for ordering.
constexpr address(uint64_t raw)
Constructs an address from a raw 64-bit value.
Definition onewire.hpp:56
static constexpr address any()
Returns the wildcard address for single-device buses.
Definition onewire.hpp:67
static constexpr address none()
Returns an invalid sentinel address indicating no device.
Definition onewire.hpp:77
1-Wire bus controller with thread-safe access.
Definition onewire.hpp:170
bool try_lock() const noexcept
Tries to acquire exclusive access without blocking.
Definition onewire.hpp:208
bus(const bus &)=delete
void unlock() const
Releases exclusive access to the bus.
Definition onewire.hpp:216
result< void > try_skip_rom()
Selects all devices on the bus.
result< void > try_read(std::span< uint8_t > buf)
Reads multiple bytes from the bus into a buffer.
result< std::vector< address > > try_search(uint8_t family_code, size_t max_devices=8)
Searches for devices with a specific family code.
void power()
Actively drives the bus high for parasitic power.
Definition onewire.hpp:373
std::vector< address > search(size_t max_devices=8)
Searches for all devices on the bus.
Definition onewire.hpp:405
static result< bus > make(gpio pin)
Creates a new 1-Wire bus controller.
uint8_t read()
Reads a single byte from the bus.
Definition onewire.hpp:334
result< void > try_write(uint8_t value)
Writes a single byte to the bus.
void read(std::span< uint8_t > buf)
Reads multiple bytes from the bus into a buffer.
Definition onewire.hpp:343
void lock() const
Acquires exclusive access to the bus.
Definition onewire.hpp:200
void write(std::span< const uint8_t > data)
Writes multiple bytes to the bus.
Definition onewire.hpp:305
gpio pin() const noexcept
Returns the GPIO pin.
Definition onewire.hpp:224
result< void > try_power()
Actively drives the bus high for parasitic power.
result< void > try_select(address addr)
Selects a specific device by ROM address.
result< uint8_t > try_read()
Reads a single byte from the bus.
bus(gpio pin)
Creates a new 1-Wire bus controller.
void depower() noexcept
Stops driving power onto the bus.
bool reset()
Performs a 1-Wire reset cycle.
result< std::vector< address > > try_search(size_t max_devices=8)
Searches for all devices on the bus.
bus & operator=(bus &&other) noexcept=default
std::vector< address > search(uint8_t family_code, size_t max_devices=8)
Searches for devices with a specific family code.
Definition onewire.hpp:416
bus & operator=(const bus &)=delete
void select(address addr)
Selects a specific device by ROM address.
Definition onewire.hpp:251
result< void > try_write(std::span< const uint8_t > data)
Writes multiple bytes to the bus.
void write(uint8_t value)
Writes a single byte to the bus.
Definition onewire.hpp:296
void skip_rom()
Selects all devices on the bus.
Definition onewire.hpp:262
bus(bus &&other) noexcept=default
std::string to_string(core_id c)
Returns a string representation of a CPU core identifier.
Definition cpu.hpp:52
bool check_crc16(std::span< const uint8_t > data, std::span< const uint8_t, 2 > inverted_crc, uint16_t crc_iv=0)
Verifies a 16-bit CRC against received data.
uint8_t crc8(std::span< const uint8_t > data)
Computes a Dallas Semiconductor 8-bit CRC.
uint16_t crc16(std::span< const uint8_t > data, uint16_t crc_iv=0)
Computes a Dallas Semiconductor 16-bit CRC.
1-Wire bus protocol classes and utilities.
Definition onewire.hpp:35
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
result< std::unique_ptr< T > > make_unique(Args &&... args)
Constructs a T via its make() factory and wraps it in a std::unique_ptr.
Definition error.hpp:157
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120