idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
master.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#include <idfxx/intr_alloc>
24
25#include <array>
26#include <cassert>
27#include <chrono>
28#include <concepts>
29#include <frequency/frequency>
30#include <functional>
31#include <initializer_list>
32#include <memory>
33#include <mutex>
34#include <optional>
35#include <span>
36#include <string>
37#include <vector>
38
39typedef struct i2c_master_bus_t* i2c_master_bus_handle_t;
40typedef struct i2c_master_dev_t* i2c_master_dev_handle_t;
41
46namespace idfxx::i2c {
47
49static constexpr auto DEFAULT_TIMEOUT = std::chrono::milliseconds(50);
50
55enum class port : int {
56 i2c0 = 0,
57#if SOC_HP_I2C_NUM >= 2
58 i2c1 = 1,
59#endif
60#if SOC_LP_I2C_NUM >= 1
61 lp_i2c0 = 2,
62#endif
63};
64
65// Clock source enums use sequential values rather than matching the ESP-IDF
66// constants directly, since the underlying SOC_MOD_CLK_* values differ per
67// target. Conversion to ESP-IDF types is done in the implementation.
68
73enum class clk_source : int {
74 default_source = 0,
75#if SOC_I2C_SUPPORT_APB
76 apb,
77#endif
78#if SOC_I2C_SUPPORT_REF_TICK
79 ref_tick,
80#endif
81#if SOC_I2C_SUPPORT_XTAL
82 xtal,
83#endif
84#if SOC_I2C_SUPPORT_RTC
85 rc_fast,
86#endif
87};
88
89#if SOC_LP_I2C_SUPPORTED
94enum class lp_clk_source : int {
95 default_source = 0,
96 lp_fast,
97 xtal_d2,
98};
99#endif
100
105enum class operation_command : int {
106 start = 0,
107 write = 1,
108 read = 2,
109 stop = 3,
110};
111
116enum class ack_value : uint8_t {
117 ack = 0,
118 nack = 1,
119};
120
133struct operation {
135 bool ack_check = true;
136 std::span<const uint8_t> write_data;
137 std::span<uint8_t> read_data;
139};
140
154public:
170 struct config {
173 freq::hertz frequency{0};
175#if SOC_LP_I2C_SUPPORTED
176 enum lp_clk_source lp_source_clk = lp_clk_source::default_source;
177#endif
179 std::optional<idfxx::intr_level> intr_level = {};
180 size_t trans_queue_depth = 0;
182 bool allow_pd = false;
183 };
184
185#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
204 [[nodiscard]] explicit master_bus(enum port port, const struct config& config);
205
217 [[nodiscard]] explicit master_bus(enum port port, gpio sda, gpio scl, freq::hertz frequency);
218#endif
219
237 [[nodiscard]] static result<master_bus> make(enum port port, const struct config& config);
238
249 [[nodiscard]] static result<master_bus> make(enum port port, gpio sda, gpio scl, freq::hertz frequency);
250
252
253 master_bus(const master_bus&) = delete;
254 master_bus& operator=(const master_bus&) = delete;
255 master_bus(master_bus&& other) noexcept;
256 master_bus& operator=(master_bus&& other) noexcept;
257
259 void lock() const {
260 if (!_mux) {
261 return;
262 }
263 _mux->lock();
264 }
265
268 if (!_mux) {
269 return false;
270 }
271 return _mux->try_lock();
272 }
273
275 void unlock() const {
276 if (!_mux) {
277 return;
278 }
279 _mux->unlock();
280 }
281
283 [[nodiscard]] i2c_master_bus_handle_t handle() const { return _handle; }
284
286 [[nodiscard]] enum port port() const { return _port; }
287
289 [[nodiscard]] freq::hertz frequency() const { return _frequency; }
290
298 [[nodiscard]] std::vector<uint8_t> scan_devices() const { return scan_devices(DEFAULT_TIMEOUT); }
299
309 template<typename Rep, typename Period>
310 [[nodiscard]] std::vector<uint8_t> scan_devices(const std::chrono::duration<Rep, Period>& timeout) const {
311 return _scan_devices(std::chrono::ceil<std::chrono::milliseconds>(timeout));
312 }
313
314#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
323 void probe(uint16_t address) const { probe(address, DEFAULT_TIMEOUT); }
324
334 template<typename Rep, typename Period>
335 void probe(uint16_t address, const std::chrono::duration<Rep, Period>& timeout) const {
336 unwrap(_probe(address, std::chrono::ceil<std::chrono::milliseconds>(timeout)));
337 }
338#endif
339
347 [[nodiscard]] result<void> try_probe(uint16_t address) const { return try_probe(address, DEFAULT_TIMEOUT); }
348
357 template<typename Rep, typename Period>
358 [[nodiscard]] result<void> try_probe(uint16_t address, const std::chrono::duration<Rep, Period>& timeout) const {
359 return _probe(address, std::chrono::ceil<std::chrono::milliseconds>(timeout));
360 }
361
362#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
374 template<typename Rep, typename Period>
375 void wait_all_done(const std::chrono::duration<Rep, Period>& timeout) const {
377 }
378#endif
379
390 template<typename Rep, typename Period>
391 [[nodiscard]] result<void> try_wait_all_done(const std::chrono::duration<Rep, Period>& timeout) const {
392 return _try_wait_all_done(std::chrono::ceil<std::chrono::milliseconds>(timeout));
393 }
394
395private:
396 explicit master_bus(i2c_master_bus_handle_t handle, enum port port, freq::hertz frequency);
397
398 void _delete() noexcept;
399
400 [[nodiscard]] std::vector<uint8_t> _scan_devices(std::chrono::milliseconds timeout) const;
401 [[nodiscard]] result<void> _probe(uint16_t address, std::chrono::milliseconds timeout) const;
402 [[nodiscard]] result<void> _try_wait_all_done(std::chrono::milliseconds timeout) const;
403
404 mutable std::unique_ptr<std::recursive_mutex> _mux;
405 i2c_master_bus_handle_t _handle = nullptr;
406 enum port _port;
407 freq::hertz _frequency;
408};
409
422public:
435 struct config {
436 freq::hertz scl_speed{0};
437 uint32_t scl_wait_us = 0;
438#if SOC_I2C_SUPPORT_10BIT_ADDR
439 bool addr_10bit = false;
440#endif
441 bool disable_ack_check = false;
442 };
443
444#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
464 [[nodiscard]] explicit master_device(master_bus& bus, uint16_t address, const struct config& config);
465
478 [[nodiscard]] explicit master_device(master_bus& bus, uint16_t address);
479#endif
480
499 [[nodiscard]] static result<master_device> make(master_bus& bus, uint16_t address, const struct config& config);
500
513
515
516 master_device(const master_device&) = delete;
518 master_device(master_device&& other) noexcept;
520
525 [[nodiscard]] master_bus& bus() const {
526 assert(_bus != nullptr);
527 return *_bus;
528 }
529
531 [[nodiscard]] i2c_master_dev_handle_t handle() const { return _handle; }
532
534 [[nodiscard]] uint16_t address() const { return _address; }
535
536#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
543 void probe() const { probe(DEFAULT_TIMEOUT); }
544
553 template<typename Rep, typename Period>
554 void probe(const std::chrono::duration<Rep, Period>& timeout) const {
556 }
557#endif
558
565
573 template<typename Rep, typename Period>
574 [[nodiscard]] result<void> try_probe(const std::chrono::duration<Rep, Period>& timeout) const {
575 if (_handle == nullptr) {
577 }
578 return _bus->try_probe(_address, std::chrono::ceil<std::chrono::milliseconds>(timeout));
579 }
580
581#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
590 void transmit(std::span<const uint8_t> data) { unwrap(try_transmit(data)); }
591
609 template<std::convertible_to<std::span<const uint8_t>>... Buffers>
610 requires(sizeof...(Buffers) > 1)
611 void transmit(Buffers... buffers) {
612 unwrap(try_transmit(buffers...));
613 }
614
626 void transmit(std::span<const std::span<const uint8_t>> buffers) { unwrap(try_transmit(buffers)); }
627
637 template<typename Rep, typename Period>
638 void transmit(std::span<const uint8_t> data, const std::chrono::duration<Rep, Period>& timeout) {
639 unwrap(try_transmit(data, timeout));
640 }
641
654 template<typename Rep, typename Period>
655 void
656 transmit(std::span<const std::span<const uint8_t>> buffers, const std::chrono::duration<Rep, Period>& timeout) {
657 unwrap(try_transmit(buffers, timeout));
658 }
659
669 void transmit(const uint8_t* buf, size_t size) { unwrap(try_transmit(buf, size)); }
670
681 template<typename Rep, typename Period>
682 void transmit(const uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
683 unwrap(try_transmit(buf, size, timeout));
684 }
685#endif
686
694 [[nodiscard]] result<void> try_transmit(std::span<const uint8_t> data) {
695 return try_transmit(data, DEFAULT_TIMEOUT);
696 }
697
708 template<std::convertible_to<std::span<const uint8_t>>... Buffers>
709 requires(sizeof...(Buffers) > 1)
711 std::array<std::span<const uint8_t>, sizeof...(Buffers)> arr{buffers...};
712 return try_transmit(std::span<const std::span<const uint8_t>>{arr});
713 }
714
725 [[nodiscard]] result<void> try_transmit(std::span<const std::span<const uint8_t>> buffers) {
726 return try_transmit(buffers, DEFAULT_TIMEOUT);
727 }
728
737 template<typename Rep, typename Period>
739 try_transmit(std::span<const uint8_t> data, const std::chrono::duration<Rep, Period>& timeout) {
740 return try_transmit(data.data(), data.size(), timeout);
741 }
742
754 template<typename Rep, typename Period>
756 try_transmit(std::span<const std::span<const uint8_t>> buffers, const std::chrono::duration<Rep, Period>& timeout) {
757 return _try_multi_buffer_transmit(buffers, std::chrono::ceil<std::chrono::milliseconds>(timeout));
758 }
759
768 [[nodiscard]] result<void> try_transmit(const uint8_t* buf, size_t size) {
769 return try_transmit(buf, size, DEFAULT_TIMEOUT);
770 }
771
781 template<typename Rep, typename Period>
783 try_transmit(const uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
784 return _try_transmit(buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
785 }
786
787#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
799 void change_address(uint16_t new_address) { unwrap(try_change_address(new_address)); }
800
813 template<typename Rep, typename Period>
814 void change_address(uint16_t new_address, const std::chrono::duration<Rep, Period>& timeout) {
815 unwrap(try_change_address(new_address, timeout));
816 }
817#endif
818
832
844 template<typename Rep, typename Period>
846 try_change_address(uint16_t new_address, const std::chrono::duration<Rep, Period>& timeout) {
847 return _try_change_address(new_address, std::chrono::ceil<std::chrono::milliseconds>(timeout));
848 }
849
850#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
863 void register_event_callbacks(std::move_only_function<bool() const> on_trans_done) {
864 unwrap(try_register_event_callbacks(std::move(on_trans_done)));
865 }
866#endif
867
879 [[nodiscard]] result<void> try_register_event_callbacks(std::move_only_function<bool() const> on_trans_done);
880
881#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
908 void execute_operations(std::span<const operation> ops) { unwrap(try_execute_operations(ops)); }
909
919 template<typename Rep, typename Period>
920 void execute_operations(std::span<const operation> ops, const std::chrono::duration<Rep, Period>& timeout) {
921 unwrap(try_execute_operations(ops, timeout));
922 }
923#endif
924
935 [[nodiscard]] result<void> try_execute_operations(std::span<const operation> ops) {
936 return try_execute_operations(ops, DEFAULT_TIMEOUT);
937 }
938
947 template<typename Rep, typename Period>
949 try_execute_operations(std::span<const operation> ops, const std::chrono::duration<Rep, Period>& timeout) {
950 return _try_execute_operations(ops, std::chrono::ceil<std::chrono::milliseconds>(timeout));
951 }
952
953#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
964 [[nodiscard]] std::vector<uint8_t> receive(size_t size) { return unwrap(try_receive(size)); }
965
977 template<typename Rep, typename Period>
978 [[nodiscard]] std::vector<uint8_t> receive(size_t size, const std::chrono::duration<Rep, Period>& timeout) {
979 return unwrap(try_receive(size, timeout));
980 }
981
991 void receive(uint8_t* buf, size_t size) { unwrap(try_receive(buf, size)); }
992
1003 template<typename Rep, typename Period>
1004 void receive(uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1005 unwrap(try_receive(buf, size, timeout));
1006 }
1007
1016 void receive(std::span<uint8_t> buf) { unwrap(try_receive(buf)); }
1017
1027 template<typename Rep, typename Period>
1028 void receive(std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1029 unwrap(try_receive(buf, timeout));
1030 }
1031#endif
1032
1041
1050 template<typename Rep, typename Period>
1052 try_receive(size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1053 std::vector<uint8_t> buf(size);
1054 return try_receive(buf, timeout).transform([&]() { return buf; });
1055 }
1056
1066 return try_receive(buf, size, DEFAULT_TIMEOUT);
1067 }
1068
1078 template<typename Rep, typename Period>
1080 try_receive(uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1081 return _try_receive(buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1082 }
1083
1092
1101 template<typename Rep, typename Period>
1102 [[nodiscard]] result<void> try_receive(std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1103 return try_receive(buf.data(), buf.size(), timeout);
1104 }
1105
1106#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1116 void write_register(uint16_t reg, std::span<const uint8_t> buf) { unwrap(try_write_register(reg, buf)); }
1117
1128 template<typename Rep, typename Period>
1129 void write_register(uint16_t reg, std::span<const uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1130 unwrap(try_write_register(reg, buf, timeout));
1131 }
1132
1143 void write_register(uint16_t reg, const uint8_t* buf, size_t size) { unwrap(try_write_register(reg, buf, size)); }
1144
1156 template<typename Rep, typename Period>
1157 void
1158 write_register(uint16_t reg, const uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1159 unwrap(try_write_register(reg, buf, size, timeout));
1160 }
1161#endif
1162
1171 [[nodiscard]] result<void> try_write_register(uint16_t reg, std::span<const uint8_t> buf) {
1172 return try_write_register(reg, buf.data(), buf.size(), DEFAULT_TIMEOUT);
1173 }
1174
1184 template<typename Rep, typename Period>
1186 try_write_register(uint16_t reg, std::span<const uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1187 return try_write_register(reg, buf.data(), buf.size(), timeout);
1188 }
1189
1200 return try_write_register(reg, buf, size, DEFAULT_TIMEOUT);
1201 }
1202
1213 template<typename Rep, typename Period>
1215 uint16_t reg,
1216 const uint8_t* buf,
1217 size_t size,
1218 const std::chrono::duration<Rep, Period>& timeout
1219 ) {
1220 return _try_write_register(reg, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1221 }
1222
1223#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1234 void write_register(uint8_t high, uint8_t low, std::span<const uint8_t> buf) {
1235 unwrap(try_write_register(high, low, buf));
1236 }
1237
1249 template<typename Rep, typename Period>
1251 uint8_t high,
1252 uint8_t low,
1253 std::span<const uint8_t> buf,
1254 const std::chrono::duration<Rep, Period>& timeout
1255 ) {
1256 unwrap(try_write_register(high, low, buf, timeout));
1257 }
1258
1270 void write_register(uint8_t high, uint8_t low, const uint8_t* buf, size_t size) {
1271 unwrap(try_write_register(high, low, buf, size));
1272 }
1273
1286 template<typename Rep, typename Period>
1288 uint8_t high,
1289 uint8_t low,
1290 const uint8_t* buf,
1291 size_t size,
1292 const std::chrono::duration<Rep, Period>& timeout
1293 ) {
1294 unwrap(try_write_register(high, low, buf, size, timeout));
1295 }
1296#endif
1297
1307 [[nodiscard]] result<void> try_write_register(uint8_t high, uint8_t low, std::span<const uint8_t> buf) {
1308 return try_write_register(high, low, buf, DEFAULT_TIMEOUT);
1309 }
1310
1321 template<typename Rep, typename Period>
1323 uint8_t high,
1324 uint8_t low,
1325 std::span<const uint8_t> buf,
1326 const std::chrono::duration<Rep, Period>& timeout
1327 ) {
1328 return try_write_register(high, low, buf.data(), buf.size(), timeout);
1329 }
1330
1342 return try_write_register(high, low, buf, size, DEFAULT_TIMEOUT);
1343 }
1344
1356 template<typename Rep, typename Period>
1358 uint8_t high,
1359 uint8_t low,
1360 const uint8_t* buf,
1361 size_t size,
1362 const std::chrono::duration<Rep, Period>& timeout
1363 ) {
1364 return _try_write_register(high, low, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1365 }
1366
1367#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1377 void write_registers(std::span<const uint16_t> registers, std::span<const uint8_t> buf) {
1378 unwrap(try_write_registers(registers, buf));
1379 }
1380
1391 template<typename Rep, typename Period>
1393 std::span<const uint16_t> registers,
1394 std::span<const uint8_t> buf,
1395 const std::chrono::duration<Rep, Period>& timeout
1396 ) {
1397 unwrap(try_write_registers(registers, buf, timeout));
1398 }
1399
1410 void write_registers(std::span<const uint16_t> registers, const uint8_t* buf, size_t size) {
1411 unwrap(try_write_registers(registers, buf, size));
1412 }
1413
1425 template<typename Rep, typename Period>
1427 std::span<const uint16_t> registers,
1428 const uint8_t* buf,
1429 size_t size,
1430 const std::chrono::duration<Rep, Period>& timeout
1431 ) {
1432 unwrap(try_write_registers(registers, buf, size, timeout));
1433 }
1434
1435 // C++23: std::span cannot be constructed from a braced initializer list until C++26 (P2447).
1436 // Remove these overloads when C++26 becomes the minimum standard.
1437
1447 void write_registers(std::initializer_list<uint16_t> registers, std::span<const uint8_t> buf) {
1448 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf);
1449 }
1450
1461 template<typename Rep, typename Period>
1463 std::initializer_list<uint16_t> registers,
1464 std::span<const uint8_t> buf,
1465 const std::chrono::duration<Rep, Period>& timeout
1466 ) {
1467 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, timeout);
1468 }
1469
1480 void write_registers(std::initializer_list<uint16_t> registers, const uint8_t* buf, size_t size) {
1481 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size);
1482 }
1483
1495 template<typename Rep, typename Period>
1497 std::initializer_list<uint16_t> registers,
1498 const uint8_t* buf,
1499 size_t size,
1500 const std::chrono::duration<Rep, Period>& timeout
1501 ) {
1502 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size, timeout);
1503 }
1504#endif
1505
1514 [[nodiscard]] result<void> try_write_registers(std::span<const uint16_t> registers, std::span<const uint8_t> buf) {
1515 return try_write_registers(registers, buf, DEFAULT_TIMEOUT);
1516 }
1517
1527 template<typename Rep, typename Period>
1529 std::span<const uint16_t> registers,
1530 std::span<const uint8_t> buf,
1531 const std::chrono::duration<Rep, Period>& timeout
1532 ) {
1533 return try_write_registers(registers, buf.data(), buf.size(), timeout);
1534 }
1535
1546 try_write_registers(std::span<const uint16_t> registers, const uint8_t* buf, size_t size) {
1547 return try_write_registers(registers, buf, size, DEFAULT_TIMEOUT);
1548 }
1549
1560 template<typename Rep, typename Period>
1562 std::span<const uint16_t> registers,
1563 const uint8_t* buf,
1564 size_t size,
1565 const std::chrono::duration<Rep, Period>& timeout
1566 ) {
1567 return _try_write_registers(registers, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1568 }
1569
1570 // C++23: std::span cannot be constructed from a braced initializer list until C++26 (P2447).
1571 // Remove these overloads when C++26 becomes the minimum standard.
1572
1582 try_write_registers(std::initializer_list<uint16_t> registers, std::span<const uint8_t> buf) {
1583 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf);
1584 }
1585
1595 template<typename Rep, typename Period>
1597 std::initializer_list<uint16_t> registers,
1598 std::span<const uint8_t> buf,
1599 const std::chrono::duration<Rep, Period>& timeout
1600 ) {
1601 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, timeout);
1602 }
1603
1614 try_write_registers(std::initializer_list<uint16_t> registers, const uint8_t* buf, size_t size) {
1615 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size);
1616 }
1617
1628 template<typename Rep, typename Period>
1630 std::initializer_list<uint16_t> registers,
1631 const uint8_t* buf,
1632 size_t size,
1633 const std::chrono::duration<Rep, Period>& timeout
1634 ) {
1635 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size, timeout);
1636 }
1637
1638#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1650 [[nodiscard]] std::vector<uint8_t> read_register(uint16_t reg, size_t size) {
1651 return unwrap(try_read_register(reg, size));
1652 }
1653
1666 template<typename Rep, typename Period>
1667 [[nodiscard]] std::vector<uint8_t>
1668 read_register(uint16_t reg, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1669 return unwrap(try_read_register(reg, size, timeout));
1670 }
1671
1681 void read_register(uint16_t reg, std::span<uint8_t> buf) { unwrap(try_read_register(reg, buf)); }
1682
1693 template<typename Rep, typename Period>
1694 void read_register(uint16_t reg, std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1695 unwrap(try_read_register(reg, buf, timeout));
1696 }
1697
1708 void read_register(uint16_t reg, uint8_t* buf, size_t size) { unwrap(try_read_register(reg, buf, size)); }
1709
1721 template<typename Rep, typename Period>
1722 void read_register(uint16_t reg, uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1723 unwrap(try_read_register(reg, buf, size, timeout));
1724 }
1725#endif
1726
1736 return try_read_register(reg, size, DEFAULT_TIMEOUT);
1737 }
1738
1748 template<typename Rep, typename Period>
1750 try_read_register(uint16_t reg, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1751 std::vector<uint8_t> buf(size);
1752 return try_read_register(reg, buf, timeout).transform([&]() { return buf; });
1753 }
1754
1764 return try_read_register(reg, buf, DEFAULT_TIMEOUT);
1765 }
1766
1775 template<typename Rep, typename Period>
1777 try_read_register(uint16_t reg, std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1778 return try_read_register(reg, buf.data(), buf.size(), timeout);
1779 }
1780
1791 return try_read_register(reg, buf, size, DEFAULT_TIMEOUT);
1792 }
1793
1804 template<typename Rep, typename Period>
1806 try_read_register(uint16_t reg, uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1807 return _try_read_register(reg, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1808 }
1809
1810#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1823 [[nodiscard]] std::vector<uint8_t> read_register(uint8_t high, uint8_t low, size_t size) {
1824 return unwrap(try_read_register(high, low, size));
1825 }
1826
1840 template<typename Rep, typename Period>
1841 [[nodiscard]] std::vector<uint8_t>
1842 read_register(uint8_t high, uint8_t low, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1843 return unwrap(try_read_register(high, low, size, timeout));
1844 }
1845
1857 void read_register(uint8_t high, uint8_t low, uint8_t* buf, size_t size) {
1858 unwrap(try_read_register(high, low, buf, size));
1859 }
1860
1873 template<typename Rep, typename Period>
1875 uint8_t high,
1876 uint8_t low,
1877 uint8_t* buf,
1878 size_t size,
1879 const std::chrono::duration<Rep, Period>& timeout
1880 ) {
1881 unwrap(try_read_register(high, low, buf, size, timeout));
1882 }
1883#endif
1884
1895 return try_read_register(high, low, size, DEFAULT_TIMEOUT);
1896 }
1897
1908 template<typename Rep, typename Period>
1910 try_read_register(uint8_t high, uint8_t low, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1911 std::vector<uint8_t> buf(size);
1912 return try_read_register(high, low, buf, timeout).transform([&]() { return buf; });
1913 }
1914
1924 [[nodiscard]] result<void> try_read_register(uint8_t high, uint8_t low, std::span<uint8_t> buf) {
1925 return try_read_register(high, low, buf, DEFAULT_TIMEOUT);
1926 }
1927
1938 template<typename Rep, typename Period>
1940 uint8_t high,
1941 uint8_t low,
1942 std::span<uint8_t> buf,
1943 const std::chrono::duration<Rep, Period>& timeout
1944 ) {
1945 return try_read_register(high, low, buf.data(), buf.size(), timeout);
1946 }
1947
1959 return try_read_register(high, low, buf, size, DEFAULT_TIMEOUT);
1960 }
1961
1973 template<typename Rep, typename Period>
1975 uint8_t high,
1976 uint8_t low,
1977 uint8_t* buf,
1978 size_t size,
1979 const std::chrono::duration<Rep, Period>& timeout
1980 ) {
1981 return _try_read_register(high, low, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1982 }
1983
1984private:
1986
1987 void _delete() noexcept;
1988
1989 [[nodiscard]] result<void> _try_transmit(const uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
1990 [[nodiscard]] result<void>
1991 _try_multi_buffer_transmit(std::span<const std::span<const uint8_t>> buffers, std::chrono::milliseconds timeout);
1992 [[nodiscard]] result<void> _try_change_address(uint16_t new_address, std::chrono::milliseconds timeout);
1993 [[nodiscard]] result<void>
1994 _try_execute_operations(std::span<const operation> ops, std::chrono::milliseconds timeout);
1995 [[nodiscard]] result<void> _try_receive(uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
1996
1997 [[nodiscard]] result<void>
1998 _try_write_register(uint16_t reg, const uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
1999 [[nodiscard]] result<void>
2000 _try_write_register(uint8_t high, uint8_t low, const uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
2001 [[nodiscard]] result<void> _try_write_registers(
2003 const uint8_t* buf,
2004 size_t size,
2005 std::chrono::milliseconds timeout
2006 );
2007 [[nodiscard]] result<void>
2008 _try_read_register(uint16_t reg, uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
2009 [[nodiscard]] result<void>
2010 _try_read_register(uint8_t high, uint8_t low, uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
2011
2012 master_bus* _bus = nullptr;
2013 i2c_master_dev_handle_t _handle = nullptr;
2014 uint16_t _address = 0;
2015 std::unique_ptr<std::move_only_function<bool() const>> _on_trans_done;
2016};
2017
// end of idfxx_i2c
2019
2020} // namespace idfxx::i2c
2021
2023
2031[[nodiscard]] inline std::string to_string(i2c::port p) {
2032 switch (p) {
2033 case i2c::port::i2c0:
2034 return "I2C0";
2035#if SOC_HP_I2C_NUM >= 2
2036 case i2c::port::i2c1:
2037 return "I2C1";
2038#endif
2039#if SOC_LP_I2C_NUM >= 1
2040 case i2c::port::lp_i2c0:
2041 return "LP_I2C0";
2042#endif
2043 default:
2044 return "unknown(" + std::to_string(static_cast<int>(p)) + ")";
2045 }
2046}
2047
2048} // namespace idfxx
2049
2050#include "sdkconfig.h"
2051#ifdef CONFIG_IDFXX_STD_FORMAT
2053#include <algorithm>
2054#include <format>
2055namespace std {
2056template<>
2057struct formatter<idfxx::i2c::port> {
2058 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
2059
2060 template<typename FormatContext>
2061 auto format(idfxx::i2c::port p, FormatContext& ctx) const {
2062 auto s = idfxx::to_string(p);
2063 return std::copy(s.begin(), s.end(), ctx.out());
2064 }
2065};
2066} // namespace std
2068#endif // CONFIG_IDFXX_STD_FORMAT
A GPIO pin.
Definition gpio.hpp:62
static constexpr gpio nc()
Returns a GPIO representing "not connected".
Definition gpio.hpp:255
I2C master bus controller with thread-safe device access.
Definition master.hpp:153
master_bus(enum port port, gpio sda, gpio scl, freq::hertz frequency)
Creates a new I2C master bus with default settings.
result< void > try_probe(uint16_t address) const
Probes for a device at the specified address.
Definition master.hpp:347
std::vector< uint8_t > scan_devices() const
Scans for devices on the bus.
Definition master.hpp:298
enum port port() const
Returns the I2C port.
Definition master.hpp:286
std::vector< uint8_t > scan_devices(const std::chrono::duration< Rep, Period > &timeout) const
Scans for devices on the bus.
Definition master.hpp:310
void probe(uint16_t address, const std::chrono::duration< Rep, Period > &timeout) const
Probes for a device at the specified address.
Definition master.hpp:335
master_bus & operator=(const master_bus &)=delete
static result< master_bus > make(enum port port, gpio sda, gpio scl, freq::hertz frequency)
Creates a new I2C master bus with default settings.
void wait_all_done(const std::chrono::duration< Rep, Period > &timeout) const
Waits for all pending asynchronous operations on the bus to complete.
Definition master.hpp:375
result< void > try_probe(uint16_t address, const std::chrono::duration< Rep, Period > &timeout) const
Probes for a device at the specified address.
Definition master.hpp:358
static result< master_bus > make(enum port port, const struct config &config)
Creates a new I2C master bus.
i2c_master_bus_handle_t handle() const
Returns the underlying ESP-IDF bus handle.
Definition master.hpp:283
freq::hertz frequency() const
Returns the bus clock frequency in Hz.
Definition master.hpp:289
void unlock() const
Releases exclusive access to the bus.
Definition master.hpp:275
master_bus(const master_bus &)=delete
master_bus(master_bus &&other) noexcept
bool try_lock() const noexcept
Tries to acquire exclusive access without blocking.
Definition master.hpp:267
master_bus(enum port port, const struct config &config)
Creates a new I2C master bus.
void probe(uint16_t address) const
Probes for a device at the specified address.
Definition master.hpp:323
result< void > try_wait_all_done(const std::chrono::duration< Rep, Period > &timeout) const
Waits for all pending asynchronous operations on the bus to complete.
Definition master.hpp:391
void lock() const
Acquires exclusive access to the bus.
Definition master.hpp:259
master_bus & operator=(master_bus &&other) noexcept
I2C device at a specific address with register operations.
Definition master.hpp:421
void transmit(const uint8_t *buf, size_t size)
Transmits data to the device.
Definition master.hpp:669
result< void > try_write_registers(std::span< const uint16_t > registers, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1561
result< void > try_probe() const
Probes the device.
Definition master.hpp:564
result< void > try_read_register(uint16_t reg, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1806
void read_register(uint8_t high, uint8_t low, uint8_t *buf, size_t size)
Reads data from a register.
Definition master.hpp:1857
void write_registers(std::span< const uint16_t > registers, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1392
result< void > try_write_register(uint16_t reg, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1214
result< std::vector< uint8_t > > try_receive(size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:1052
void write_registers(std::initializer_list< uint16_t > registers, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1496
void write_register(uint8_t high, uint8_t low, std::span< const uint8_t > buf)
Writes data to a register.
Definition master.hpp:1234
result< void > try_execute_operations(std::span< const operation > ops)
Executes a custom sequence of I2C operations.
Definition master.hpp:935
void write_register(uint16_t reg, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1158
result< void > try_write_registers(std::span< const uint16_t > registers, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1528
void write_register(uint16_t reg, const uint8_t *buf, size_t size)
Writes data to a register.
Definition master.hpp:1143
result< void > try_write_register(uint8_t high, uint8_t low, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1322
void write_register(uint8_t high, uint8_t low, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1250
std::vector< uint8_t > read_register(uint16_t reg, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1668
master_device(master_bus &bus, uint16_t address)
Creates a new device on the specified bus.
result< std::vector< uint8_t > > try_read_register(uint16_t reg, size_t size)
Reads data from a register.
Definition master.hpp:1735
void register_event_callbacks(std::move_only_function< bool() const > on_trans_done)
Registers a callback for transaction-done events.
Definition master.hpp:863
void write_registers(std::initializer_list< uint16_t > registers, std::span< const uint8_t > buf)
Writes data to multiple registers.
Definition master.hpp:1447
result< void > try_write_registers(std::initializer_list< uint16_t > registers, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1596
void write_register(uint16_t reg, std::span< const uint8_t > buf)
Writes data to a register.
Definition master.hpp:1116
result< void > try_read_register(uint8_t high, uint8_t low, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1974
void read_register(uint16_t reg, std::span< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1694
result< void > try_write_registers(std::initializer_list< uint16_t > registers, const uint8_t *buf, size_t size)
Writes data to multiple registers.
Definition master.hpp:1614
void write_registers(std::span< const uint16_t > registers, const uint8_t *buf, size_t size)
Writes data to multiple registers.
Definition master.hpp:1410
result< void > try_write_register(uint8_t high, uint8_t low, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1357
result< void > try_write_registers(std::span< const uint16_t > registers, const uint8_t *buf, size_t size)
Writes data to multiple registers.
Definition master.hpp:1546
result< void > try_read_register(uint16_t reg, std::span< uint8_t > buf)
Reads data from a register.
Definition master.hpp:1763
result< void > try_write_register(uint8_t high, uint8_t low, const uint8_t *buf, size_t size)
Writes data to a register.
Definition master.hpp:1341
void transmit(std::span< const uint8_t > data, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
Definition master.hpp:638
void receive(uint8_t *buf, size_t size)
Receives data from the device.
Definition master.hpp:991
result< void > try_register_event_callbacks(std::move_only_function< bool() const > on_trans_done)
Registers a callback for transaction-done events.
void probe() const
Probes the device.
Definition master.hpp:543
result< void > try_read_register(uint8_t high, uint8_t low, uint8_t *buf, size_t size)
Reads data from a register.
Definition master.hpp:1958
void receive(uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:1004
result< void > try_receive(uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:1080
void probe(const std::chrono::duration< Rep, Period > &timeout) const
Probes the device.
Definition master.hpp:554
result< std::vector< uint8_t > > try_receive(size_t size)
Receives data from the device.
Definition master.hpp:1040
result< void > try_write_register(uint8_t high, uint8_t low, std::span< const uint8_t > buf)
Writes data to a register.
Definition master.hpp:1307
result< std::vector< uint8_t > > try_read_register(uint8_t high, uint8_t low, size_t size)
Reads data from a register.
Definition master.hpp:1894
result< std::vector< uint8_t > > try_read_register(uint8_t high, uint8_t low, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1910
void execute_operations(std::span< const operation > ops)
Executes a custom sequence of I2C operations.
Definition master.hpp:908
result< void > try_transmit(std::span< const std::span< const uint8_t > > buffers, const std::chrono::duration< Rep, Period > &timeout)
Transmits data from multiple buffers in a single I2C transaction.
Definition master.hpp:756
void read_register(uint8_t high, uint8_t low, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1874
result< void > try_read_register(uint8_t high, uint8_t low, std::span< uint8_t > buf)
Reads data from a register.
Definition master.hpp:1924
master_device(const master_device &)=delete
std::vector< uint8_t > read_register(uint8_t high, uint8_t low, size_t size)
Reads data from a register.
Definition master.hpp:1823
result< void > try_transmit(Buffers... buffers)
Transmits data from multiple buffers in a single I2C transaction.
Definition master.hpp:710
result< void > try_write_register(uint16_t reg, std::span< const uint8_t > buf)
Writes data to a register.
Definition master.hpp:1171
result< void > try_write_registers(std::initializer_list< uint16_t > registers, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1629
result< void > try_write_register(uint16_t reg, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1186
void transmit(std::span< const uint8_t > data)
Transmits data to the device.
Definition master.hpp:590
master_device(master_device &&other) noexcept
void write_registers(std::span< const uint16_t > registers, std::span< const uint8_t > buf)
Writes data to multiple registers.
Definition master.hpp:1377
static result< master_device > make(master_bus &bus, uint16_t address, const struct config &config)
Creates a new device on the specified bus.
void write_registers(std::initializer_list< uint16_t > registers, const uint8_t *buf, size_t size)
Writes data to multiple registers.
Definition master.hpp:1480
master_device(master_bus &bus, uint16_t address, const struct config &config)
Creates a new device on the specified bus.
void write_register(uint16_t reg, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1129
result< void > try_transmit(std::span< const std::span< const uint8_t > > buffers)
Transmits data from multiple buffers in a single I2C transaction.
Definition master.hpp:725
result< std::vector< uint8_t > > try_read_register(uint16_t reg, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1750
uint16_t address() const
Returns the device address.
Definition master.hpp:534
result< void > try_read_register(uint8_t high, uint8_t low, std::span< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1939
void read_register(uint16_t reg, uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1722
result< void > try_transmit(const uint8_t *buf, size_t size)
Transmits data to the device.
Definition master.hpp:768
void write_register(uint8_t high, uint8_t low, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to a register.
Definition master.hpp:1287
void change_address(uint16_t new_address)
Changes the I2C address used for subsequent operations.
Definition master.hpp:799
result< void > try_receive(std::span< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:1102
result< void > try_receive(uint8_t *buf, size_t size)
Receives data from the device.
Definition master.hpp:1065
i2c_master_dev_handle_t handle() const
Returns the underlying ESP-IDF device handle.
Definition master.hpp:531
void read_register(uint16_t reg, std::span< uint8_t > buf)
Reads data from a register.
Definition master.hpp:1681
void transmit(std::span< const std::span< const uint8_t > > buffers)
Transmits data from multiple buffers in a single I2C transaction.
Definition master.hpp:626
void transmit(const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
Definition master.hpp:682
result< void > try_write_register(uint16_t reg, const uint8_t *buf, size_t size)
Writes data to a register.
Definition master.hpp:1199
result< void > try_receive(std::span< uint8_t > buf)
Receives data from the device.
Definition master.hpp:1091
std::vector< uint8_t > read_register(uint8_t high, uint8_t low, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1842
result< void > try_read_register(uint16_t reg, uint8_t *buf, size_t size)
Reads data from a register.
Definition master.hpp:1790
result< void > try_transmit(const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
Definition master.hpp:783
result< void > try_transmit(std::span< const uint8_t > data)
Transmits data to the device.
Definition master.hpp:694
void write_registers(std::initializer_list< uint16_t > registers, std::span< const uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1462
std::vector< uint8_t > receive(size_t size)
Receives data from the device.
Definition master.hpp:964
std::vector< uint8_t > read_register(uint16_t reg, size_t size)
Reads data from a register.
Definition master.hpp:1650
result< void > try_change_address(uint16_t new_address)
Changes the I2C address used for subsequent operations.
Definition master.hpp:829
result< void > try_execute_operations(std::span< const operation > ops, const std::chrono::duration< Rep, Period > &timeout)
Executes a custom sequence of I2C operations.
Definition master.hpp:949
result< void > try_write_registers(std::span< const uint16_t > registers, std::span< const uint8_t > buf)
Writes data to multiple registers.
Definition master.hpp:1514
result< void > try_transmit(std::span< const uint8_t > data, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
Definition master.hpp:739
std::vector< uint8_t > receive(size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:978
result< void > try_write_registers(std::initializer_list< uint16_t > registers, std::span< const uint8_t > buf)
Writes data to multiple registers.
Definition master.hpp:1582
master_device & operator=(const master_device &)=delete
master_device & operator=(master_device &&other) noexcept
void write_register(uint8_t high, uint8_t low, const uint8_t *buf, size_t size)
Writes data to a register.
Definition master.hpp:1270
void transmit(std::span< const std::span< const uint8_t > > buffers, const std::chrono::duration< Rep, Period > &timeout)
Transmits data from multiple buffers in a single I2C transaction.
Definition master.hpp:656
result< void > try_probe(const std::chrono::duration< Rep, Period > &timeout) const
Probes the device.
Definition master.hpp:574
void receive(std::span< uint8_t > buf)
Receives data from the device.
Definition master.hpp:1016
void write_registers(std::span< const uint16_t > registers, const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Writes data to multiple registers.
Definition master.hpp:1426
void read_register(uint16_t reg, uint8_t *buf, size_t size)
Reads data from a register.
Definition master.hpp:1708
result< void > try_change_address(uint16_t new_address, const std::chrono::duration< Rep, Period > &timeout)
Changes the I2C address used for subsequent operations.
Definition master.hpp:846
master_bus & bus() const
Returns the parent bus.
Definition master.hpp:525
void change_address(uint16_t new_address, const std::chrono::duration< Rep, Period > &timeout)
Changes the I2C address used for subsequent operations.
Definition master.hpp:814
void execute_operations(std::span< const operation > ops, const std::chrono::duration< Rep, Period > &timeout)
Executes a custom sequence of I2C operations.
Definition master.hpp:920
result< void > try_read_register(uint16_t reg, std::span< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Reads data from a register.
Definition master.hpp:1777
static result< master_device > make(master_bus &bus, uint16_t address)
Creates a new device on the specified bus.
void receive(std::span< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:1028
std::string to_string(core_id c)
Returns a string representation of a CPU core identifier.
Definition cpu.hpp:52
operation_command
I2C operation command type for custom transaction sequences.
Definition master.hpp:105
struct i2c_master_bus_t * i2c_master_bus_handle_t
Definition master.hpp:39
struct i2c_master_dev_t * i2c_master_dev_handle_t
Definition master.hpp:40
ack_value
ACK value sent after a read operation.
Definition master.hpp:116
clk_source
I2C master bus clock source.
Definition master.hpp:73
port
I2C port identifiers.
Definition master.hpp:55
static constexpr auto DEFAULT_TIMEOUT
Default timeout for I2C operations.
Definition master.hpp:49
@ start
Send START or repeated-START condition.
@ read
Read data from the bus.
@ stop
Send STOP condition.
@ write
Write data to the bus.
@ ack
Acknowledge — request more data.
@ nack
Not-acknowledge — signal end of read.
@ default_source
Default clock source for the target.
@ i2c0
I2C port 0.
I2C master driver classes.
Definition master.hpp:46
intr_level
Hardware interrupt priority levels.
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
Definition error.hpp:187
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
@ invalid_state
Invalid state.
@ timeout
Operation timed out.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120
I2C master bus configuration.
Definition master.hpp:170
freq::hertz frequency
Clock frequency in Hz.
Definition master.hpp:173
bool allow_pd
Allow powering down the bus during light sleep.
Definition master.hpp:182
idfxx::gpio scl
GPIO pin for the SCL line.
Definition master.hpp:172
idfxx::gpio sda
GPIO pin for the SDA line.
Definition master.hpp:171
size_t trans_queue_depth
Depth of internal transfer queue for asynchronous transactions.
Definition master.hpp:180
uint8_t glitch_ignore_cnt
Glitch filter count (0-7). Higher values filter more noise.
Definition master.hpp:178
bool enable_internal_pullup
Enable internal pull-up resistors on SDA and SCL.
Definition master.hpp:181
I2C device configuration.
Definition master.hpp:435
Describes a single operation in a custom I2C transaction sequence.
Definition master.hpp:133
bool ack_check
(write) Whether to check for ACK.
Definition master.hpp:135
operation_command command
The operation to perform.
Definition master.hpp:134
ack_value ack_type
(read) ACK value to send after reading.
Definition master.hpp:138
std::span< const uint8_t > write_data
(write) Data to send.
Definition master.hpp:136
std::span< uint8_t > read_data
(read) Buffer to receive into.
Definition master.hpp:137