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
169class bus {
170public:
171#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
179 [[nodiscard]] explicit bus(gpio pin);
180#endif
181
189 [[nodiscard]] static result<bus> make(gpio pin);
190
191 ~bus() = default;
192
193 bus(const bus&) = delete;
194 bus& operator=(const bus&) = delete;
195 bus(bus&& other) noexcept = default;
196 bus& operator=(bus&& other) noexcept = default;
197
199 void lock() const {
200 if (!_mux) {
201 return;
202 }
203 _mux->lock();
204 }
205
207 [[nodiscard]] bool try_lock() const noexcept {
208 if (!_mux) {
209 return false;
210 }
211 return _mux->try_lock();
212 }
213
215 void unlock() const {
216 if (!_mux) {
217 return;
218 }
219 _mux->unlock();
220 }
221
223 [[nodiscard]] gpio pin() const noexcept { return _pin; }
224
225 // -- Bus reset -----------------------------------------------------------
226
235 [[nodiscard]] bool reset();
236
237 // -- ROM commands --------------------------------------------------------
238
239#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
250 void select(address addr) { unwrap(try_select(addr)); }
251
262#endif
263
273 [[nodiscard]] result<void> try_select(address addr);
274
283 [[nodiscard]] result<void> try_skip_rom();
284
285 // -- Write operations ----------------------------------------------------
286
287#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
295 void write(uint8_t value) { unwrap(try_write(value)); }
296
304 void write(std::span<const uint8_t> data) { unwrap(try_write(data)); }
305#endif
306
313 [[nodiscard]] result<void> try_write(uint8_t value);
314
321 [[nodiscard]] result<void> try_write(std::span<const uint8_t> data);
322
323 // -- Read operations -----------------------------------------------------
324
325#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
333 [[nodiscard]] uint8_t read() { return unwrap(try_read()); }
334
342 void read(std::span<uint8_t> buf) { unwrap(try_read(buf)); }
343#endif
344
350 [[nodiscard]] result<uint8_t> try_read();
351
358 [[nodiscard]] result<void> try_read(std::span<uint8_t> buf);
359
360 // -- Parasitic power -----------------------------------------------------
361
362#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
372 void power() { unwrap(try_power()); }
373#endif
374
383 [[nodiscard]] result<void> try_power();
384
391 void depower() noexcept;
392
393 // -- Device search -------------------------------------------------------
394
395#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
404 [[nodiscard]] std::vector<address> search(size_t max_devices = 8) { return unwrap(try_search(max_devices)); }
405
415 [[nodiscard]] std::vector<address> search(uint8_t family_code, size_t max_devices = 8) {
416 return unwrap(try_search(family_code, max_devices));
417 }
418#endif
419
426 [[nodiscard]] result<std::vector<address>> try_search(size_t max_devices = 8);
427
436 [[nodiscard]] result<std::vector<address>> try_search(uint8_t family_code, size_t max_devices = 8);
437
438private:
440 struct validated {};
441 bus(gpio pin, validated)
442 : _pin(pin)
443 , _mux(std::make_unique<std::recursive_mutex>()) {}
446 gpio _pin;
447 mutable std::unique_ptr<std::recursive_mutex> _mux;
448};
449
// end of idfxx_onewire
451
452} // namespace idfxx::onewire
453
454namespace idfxx {
455
465[[nodiscard]] inline std::string to_string(onewire::address addr) {
466 if (addr == onewire::address::any()) {
467 return "ONEWIRE_ANY";
468 }
469 if (addr == onewire::address::none()) {
470 return "ONEWIRE_NONE";
471 }
472 static constexpr char hex[] = "0123456789ABCDEF";
473 std::string result;
474 result.reserve(23);
475 auto raw = addr.raw();
476 for (int i = 0; i < 8; ++i) {
477 if (i > 0) {
478 result += ':';
479 }
480 auto byte = static_cast<uint8_t>((raw >> (i * 8)) & 0xFF);
481 result += hex[byte >> 4];
482 result += hex[byte & 0xF];
483 }
484 return result;
485}
486
487} // namespace idfxx
488
489#include "sdkconfig.h"
490#ifdef CONFIG_IDFXX_STD_FORMAT
492#include <algorithm>
493#include <format>
494namespace std {
495template<>
496struct formatter<idfxx::onewire::address> {
497 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
498
499 template<typename FormatContext>
500 auto format(idfxx::onewire::address addr, FormatContext& ctx) const {
501 auto s = idfxx::to_string(addr);
502 return std::copy(s.begin(), s.end(), ctx.out());
503 }
504};
505} // namespace std
507#endif // CONFIG_IDFXX_STD_FORMAT
A GPIO pin.
Definition gpio.hpp:62
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:169
bool try_lock() const noexcept
Tries to acquire exclusive access without blocking.
Definition onewire.hpp:207
bus(const bus &)=delete
void unlock() const
Releases exclusive access to the bus.
Definition onewire.hpp:215
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:372
std::vector< address > search(size_t max_devices=8)
Searches for all devices on the bus.
Definition onewire.hpp:404
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:333
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:342
void lock() const
Acquires exclusive access to the bus.
Definition onewire.hpp:199
void write(std::span< const uint8_t > data)
Writes multiple bytes to the bus.
Definition onewire.hpp:304
gpio pin() const noexcept
Returns the GPIO pin.
Definition onewire.hpp:223
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:415
bus & operator=(const bus &)=delete
void select(address addr)
Selects a specific device by ROM address.
Definition onewire.hpp:250
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:295
void skip_rom()
Selects all devices on the bus.
Definition onewire.hpp:261
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
Definition adc.hpp:48
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