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
153public:
169 struct config {
172 freq::hertz frequency{0};
174#if SOC_LP_I2C_SUPPORTED
175 enum lp_clk_source lp_source_clk = lp_clk_source::default_source;
176#endif
177 uint8_t glitch_ignore_cnt = 7;
178 std::optional<idfxx::intr_level> intr_level = {};
179 size_t trans_queue_depth = 0;
181 bool allow_pd = false;
182 };
183
184#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
203 [[nodiscard]] explicit master_bus(enum port port, const struct config& config);
204
216 [[nodiscard]] explicit master_bus(enum port port, gpio sda, gpio scl, freq::hertz frequency);
217#endif
218
236 [[nodiscard]] static result<master_bus> make(enum port port, const struct config& config);
237
248 [[nodiscard]] static result<master_bus> make(enum port port, gpio sda, gpio scl, freq::hertz frequency);
249
251
252 master_bus(const master_bus&) = delete;
253 master_bus& operator=(const master_bus&) = delete;
254 master_bus(master_bus&& other) noexcept;
255 master_bus& operator=(master_bus&& other) noexcept;
256
258 void lock() const {
259 if (!_mux) {
260 return;
261 }
262 _mux->lock();
263 }
264
266 [[nodiscard]] bool try_lock() const noexcept {
267 if (!_mux) {
268 return false;
269 }
270 return _mux->try_lock();
271 }
272
274 void unlock() const {
275 if (!_mux) {
276 return;
277 }
278 _mux->unlock();
279 }
280
282 [[nodiscard]] i2c_master_bus_handle_t handle() const { return _handle; }
283
285 [[nodiscard]] enum port port() const { return _port; }
286
288 [[nodiscard]] freq::hertz frequency() const { return _frequency; }
289
297 [[nodiscard]] std::vector<uint8_t> scan_devices() const { return scan_devices(DEFAULT_TIMEOUT); }
298
308 template<typename Rep, typename Period>
309 [[nodiscard]] std::vector<uint8_t> scan_devices(const std::chrono::duration<Rep, Period>& timeout) const {
310 return _scan_devices(std::chrono::ceil<std::chrono::milliseconds>(timeout));
311 }
312
313#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
322 void probe(uint16_t address) const { probe(address, DEFAULT_TIMEOUT); }
323
333 template<typename Rep, typename Period>
334 void probe(uint16_t address, const std::chrono::duration<Rep, Period>& timeout) const {
335 unwrap(_probe(address, std::chrono::ceil<std::chrono::milliseconds>(timeout)));
336 }
337#endif
338
346 [[nodiscard]] result<void> try_probe(uint16_t address) const { return try_probe(address, DEFAULT_TIMEOUT); }
347
356 template<typename Rep, typename Period>
357 [[nodiscard]] result<void> try_probe(uint16_t address, const std::chrono::duration<Rep, Period>& timeout) const {
358 return _probe(address, std::chrono::ceil<std::chrono::milliseconds>(timeout));
359 }
360
361#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
373 template<typename Rep, typename Period>
374 void wait_all_done(const std::chrono::duration<Rep, Period>& timeout) const {
376 }
377#endif
378
389 template<typename Rep, typename Period>
390 [[nodiscard]] result<void> try_wait_all_done(const std::chrono::duration<Rep, Period>& timeout) const {
391 return _try_wait_all_done(std::chrono::ceil<std::chrono::milliseconds>(timeout));
392 }
393
394private:
395 explicit master_bus(i2c_master_bus_handle_t handle, enum port port, freq::hertz frequency);
396
397 void _delete() noexcept;
398
399 [[nodiscard]] std::vector<uint8_t> _scan_devices(std::chrono::milliseconds timeout) const;
400 [[nodiscard]] result<void> _probe(uint16_t address, std::chrono::milliseconds timeout) const;
401 [[nodiscard]] result<void> _try_wait_all_done(std::chrono::milliseconds timeout) const;
402
403 mutable std::unique_ptr<std::recursive_mutex> _mux;
404 i2c_master_bus_handle_t _handle = nullptr;
405 enum port _port;
406 freq::hertz _frequency;
407};
408
421public:
434 struct config {
435 freq::hertz scl_speed{0};
436 uint32_t scl_wait_us = 0;
437#if SOC_I2C_SUPPORT_10BIT_ADDR
438 bool addr_10bit = false;
439#endif
440 bool disable_ack_check = false;
441 };
442
443#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
463 [[nodiscard]] explicit master_device(master_bus& bus, uint16_t address, const struct config& config);
464
477 [[nodiscard]] explicit master_device(master_bus& bus, uint16_t address);
478#endif
479
498 [[nodiscard]] static result<master_device> make(master_bus& bus, uint16_t address, const struct config& config);
499
511 [[nodiscard]] static result<master_device> make(master_bus& bus, uint16_t address);
512
514
515 master_device(const master_device&) = delete;
517 master_device(master_device&& other) noexcept;
519
524 [[nodiscard]] master_bus& bus() const {
525 assert(_bus != nullptr);
526 return *_bus;
527 }
528
530 [[nodiscard]] i2c_master_dev_handle_t handle() const { return _handle; }
531
533 [[nodiscard]] uint16_t address() const { return _address; }
534
535#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
542 void probe() const { probe(DEFAULT_TIMEOUT); }
543
552 template<typename Rep, typename Period>
553 void probe(const std::chrono::duration<Rep, Period>& timeout) const {
555 }
556#endif
557
563 [[nodiscard]] result<void> try_probe() const { return try_probe(DEFAULT_TIMEOUT); }
564
572 template<typename Rep, typename Period>
573 [[nodiscard]] result<void> try_probe(const std::chrono::duration<Rep, Period>& timeout) const {
574 if (_handle == nullptr) {
576 }
577 return _bus->try_probe(_address, std::chrono::ceil<std::chrono::milliseconds>(timeout));
578 }
579
580#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
589 void transmit(std::span<const uint8_t> data) { unwrap(try_transmit(data)); }
590
608 template<std::convertible_to<std::span<const uint8_t>>... Buffers>
609 requires(sizeof...(Buffers) > 1)
610 void transmit(Buffers... buffers) {
611 unwrap(try_transmit(buffers...));
612 }
613
625 void transmit(std::span<const std::span<const uint8_t>> buffers) { unwrap(try_transmit(buffers)); }
626
636 template<typename Rep, typename Period>
637 void transmit(std::span<const uint8_t> data, const std::chrono::duration<Rep, Period>& timeout) {
638 unwrap(try_transmit(data, timeout));
639 }
640
653 template<typename Rep, typename Period>
654 void
655 transmit(std::span<const std::span<const uint8_t>> buffers, const std::chrono::duration<Rep, Period>& timeout) {
656 unwrap(try_transmit(buffers, timeout));
657 }
658
668 void transmit(const uint8_t* buf, size_t size) { unwrap(try_transmit(buf, size)); }
669
680 template<typename Rep, typename Period>
681 void transmit(const uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
682 unwrap(try_transmit(buf, size, timeout));
683 }
684#endif
685
693 [[nodiscard]] result<void> try_transmit(std::span<const uint8_t> data) {
694 return try_transmit(data, DEFAULT_TIMEOUT);
695 }
696
707 template<std::convertible_to<std::span<const uint8_t>>... Buffers>
708 requires(sizeof...(Buffers) > 1)
709 [[nodiscard]] result<void> try_transmit(Buffers... buffers) {
710 std::array<std::span<const uint8_t>, sizeof...(Buffers)> arr{buffers...};
711 return try_transmit(std::span<const std::span<const uint8_t>>{arr});
712 }
713
724 [[nodiscard]] result<void> try_transmit(std::span<const std::span<const uint8_t>> buffers) {
725 return try_transmit(buffers, DEFAULT_TIMEOUT);
726 }
727
736 template<typename Rep, typename Period>
737 [[nodiscard]] result<void>
738 try_transmit(std::span<const uint8_t> data, const std::chrono::duration<Rep, Period>& timeout) {
739 return try_transmit(data.data(), data.size(), timeout);
740 }
741
753 template<typename Rep, typename Period>
754 [[nodiscard]] result<void>
755 try_transmit(std::span<const std::span<const uint8_t>> buffers, const std::chrono::duration<Rep, Period>& timeout) {
756 return _try_multi_buffer_transmit(buffers, std::chrono::ceil<std::chrono::milliseconds>(timeout));
757 }
758
767 [[nodiscard]] result<void> try_transmit(const uint8_t* buf, size_t size) {
768 return try_transmit(buf, size, DEFAULT_TIMEOUT);
769 }
770
780 template<typename Rep, typename Period>
781 [[nodiscard]] result<void>
782 try_transmit(const uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
783 return _try_transmit(buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
784 }
785
786#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
798 void change_address(uint16_t new_address) { unwrap(try_change_address(new_address)); }
799
812 template<typename Rep, typename Period>
813 void change_address(uint16_t new_address, const std::chrono::duration<Rep, Period>& timeout) {
814 unwrap(try_change_address(new_address, timeout));
815 }
816#endif
817
828 [[nodiscard]] result<void> try_change_address(uint16_t new_address) {
829 return try_change_address(new_address, DEFAULT_TIMEOUT);
830 }
831
843 template<typename Rep, typename Period>
844 [[nodiscard]] result<void>
845 try_change_address(uint16_t new_address, const std::chrono::duration<Rep, Period>& timeout) {
846 return _try_change_address(new_address, std::chrono::ceil<std::chrono::milliseconds>(timeout));
847 }
848
849#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
862 void register_event_callbacks(std::move_only_function<bool() const> on_trans_done) {
863 unwrap(try_register_event_callbacks(std::move(on_trans_done)));
864 }
865#endif
866
878 [[nodiscard]] result<void> try_register_event_callbacks(std::move_only_function<bool() const> on_trans_done);
879
880#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
907 void execute_operations(std::span<const operation> ops) { unwrap(try_execute_operations(ops)); }
908
918 template<typename Rep, typename Period>
919 void execute_operations(std::span<const operation> ops, const std::chrono::duration<Rep, Period>& timeout) {
920 unwrap(try_execute_operations(ops, timeout));
921 }
922#endif
923
934 [[nodiscard]] result<void> try_execute_operations(std::span<const operation> ops) {
935 return try_execute_operations(ops, DEFAULT_TIMEOUT);
936 }
937
946 template<typename Rep, typename Period>
947 [[nodiscard]] result<void>
948 try_execute_operations(std::span<const operation> ops, const std::chrono::duration<Rep, Period>& timeout) {
949 return _try_execute_operations(ops, std::chrono::ceil<std::chrono::milliseconds>(timeout));
950 }
951
952#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
963 [[nodiscard]] std::vector<uint8_t> receive(size_t size) { return unwrap(try_receive(size)); }
964
976 template<typename Rep, typename Period>
977 [[nodiscard]] std::vector<uint8_t> receive(size_t size, const std::chrono::duration<Rep, Period>& timeout) {
978 return unwrap(try_receive(size, timeout));
979 }
980
990 void receive(uint8_t* buf, size_t size) { unwrap(try_receive(buf, size)); }
991
1002 template<typename Rep, typename Period>
1003 void receive(uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1004 unwrap(try_receive(buf, size, timeout));
1005 }
1006
1015 void receive(std::span<uint8_t> buf) { unwrap(try_receive(buf)); }
1016
1026 template<typename Rep, typename Period>
1027 void receive(std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1028 unwrap(try_receive(buf, timeout));
1029 }
1030#endif
1031
1039 [[nodiscard]] result<std::vector<uint8_t>> try_receive(size_t size) { return try_receive(size, DEFAULT_TIMEOUT); }
1040
1049 template<typename Rep, typename Period>
1050 [[nodiscard]] result<std::vector<uint8_t>>
1051 try_receive(size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1052 std::vector<uint8_t> buf(size);
1053 return try_receive(buf, timeout).transform([&]() { return buf; });
1054 }
1055
1064 [[nodiscard]] result<void> try_receive(uint8_t* buf, size_t size) {
1065 return try_receive(buf, size, DEFAULT_TIMEOUT);
1066 }
1067
1077 template<typename Rep, typename Period>
1078 [[nodiscard]] result<void>
1079 try_receive(uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1080 return _try_receive(buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1081 }
1082
1090 [[nodiscard]] result<void> try_receive(std::span<uint8_t> buf) { return try_receive(buf, DEFAULT_TIMEOUT); }
1091
1100 template<typename Rep, typename Period>
1101 [[nodiscard]] result<void> try_receive(std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1102 return try_receive(buf.data(), buf.size(), timeout);
1103 }
1104
1105#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1115 void write_register(uint16_t reg, std::span<const uint8_t> buf) { unwrap(try_write_register(reg, buf)); }
1116
1127 template<typename Rep, typename Period>
1128 void write_register(uint16_t reg, std::span<const uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1129 unwrap(try_write_register(reg, buf, timeout));
1130 }
1131
1142 void write_register(uint16_t reg, const uint8_t* buf, size_t size) { unwrap(try_write_register(reg, buf, size)); }
1143
1155 template<typename Rep, typename Period>
1156 void
1157 write_register(uint16_t reg, const uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1158 unwrap(try_write_register(reg, buf, size, timeout));
1159 }
1160#endif
1161
1170 [[nodiscard]] result<void> try_write_register(uint16_t reg, std::span<const uint8_t> buf) {
1171 return try_write_register(reg, buf.data(), buf.size(), DEFAULT_TIMEOUT);
1172 }
1173
1183 template<typename Rep, typename Period>
1184 [[nodiscard]] result<void>
1185 try_write_register(uint16_t reg, std::span<const uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1186 return try_write_register(reg, buf.data(), buf.size(), timeout);
1187 }
1188
1198 [[nodiscard]] result<void> try_write_register(uint16_t reg, const uint8_t* buf, size_t size) {
1199 return try_write_register(reg, buf, size, DEFAULT_TIMEOUT);
1200 }
1201
1212 template<typename Rep, typename Period>
1214 uint16_t reg,
1215 const uint8_t* buf,
1216 size_t size,
1217 const std::chrono::duration<Rep, Period>& timeout
1218 ) {
1219 return _try_write_register(reg, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1220 }
1221
1222#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1233 void write_register(uint8_t high, uint8_t low, std::span<const uint8_t> buf) {
1234 unwrap(try_write_register(high, low, buf));
1235 }
1236
1248 template<typename Rep, typename Period>
1250 uint8_t high,
1251 uint8_t low,
1252 std::span<const uint8_t> buf,
1253 const std::chrono::duration<Rep, Period>& timeout
1254 ) {
1255 unwrap(try_write_register(high, low, buf, timeout));
1256 }
1257
1269 void write_register(uint8_t high, uint8_t low, const uint8_t* buf, size_t size) {
1270 unwrap(try_write_register(high, low, buf, size));
1271 }
1272
1285 template<typename Rep, typename Period>
1287 uint8_t high,
1288 uint8_t low,
1289 const uint8_t* buf,
1290 size_t size,
1291 const std::chrono::duration<Rep, Period>& timeout
1292 ) {
1293 unwrap(try_write_register(high, low, buf, size, timeout));
1294 }
1295#endif
1296
1306 [[nodiscard]] result<void> try_write_register(uint8_t high, uint8_t low, std::span<const uint8_t> buf) {
1307 return try_write_register(high, low, buf, DEFAULT_TIMEOUT);
1308 }
1309
1320 template<typename Rep, typename Period>
1322 uint8_t high,
1323 uint8_t low,
1324 std::span<const uint8_t> buf,
1325 const std::chrono::duration<Rep, Period>& timeout
1326 ) {
1327 return try_write_register(high, low, buf.data(), buf.size(), timeout);
1328 }
1329
1340 [[nodiscard]] result<void> try_write_register(uint8_t high, uint8_t low, const uint8_t* buf, size_t size) {
1341 return try_write_register(high, low, buf, size, DEFAULT_TIMEOUT);
1342 }
1343
1355 template<typename Rep, typename Period>
1357 uint8_t high,
1358 uint8_t low,
1359 const uint8_t* buf,
1360 size_t size,
1361 const std::chrono::duration<Rep, Period>& timeout
1362 ) {
1363 return _try_write_register(high, low, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1364 }
1365
1366#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1376 void write_registers(std::span<const uint16_t> registers, std::span<const uint8_t> buf) {
1377 unwrap(try_write_registers(registers, buf));
1378 }
1379
1390 template<typename Rep, typename Period>
1392 std::span<const uint16_t> registers,
1393 std::span<const uint8_t> buf,
1394 const std::chrono::duration<Rep, Period>& timeout
1395 ) {
1396 unwrap(try_write_registers(registers, buf, timeout));
1397 }
1398
1409 void write_registers(std::span<const uint16_t> registers, const uint8_t* buf, size_t size) {
1410 unwrap(try_write_registers(registers, buf, size));
1411 }
1412
1424 template<typename Rep, typename Period>
1426 std::span<const uint16_t> registers,
1427 const uint8_t* buf,
1428 size_t size,
1429 const std::chrono::duration<Rep, Period>& timeout
1430 ) {
1431 unwrap(try_write_registers(registers, buf, size, timeout));
1432 }
1433
1434 // C++23: std::span cannot be constructed from a braced initializer list until C++26 (P2447).
1435 // Remove these overloads when C++26 becomes the minimum standard.
1436
1446 void write_registers(std::initializer_list<uint16_t> registers, std::span<const uint8_t> buf) {
1447 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf);
1448 }
1449
1460 template<typename Rep, typename Period>
1462 std::initializer_list<uint16_t> registers,
1463 std::span<const uint8_t> buf,
1464 const std::chrono::duration<Rep, Period>& timeout
1465 ) {
1466 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, timeout);
1467 }
1468
1479 void write_registers(std::initializer_list<uint16_t> registers, const uint8_t* buf, size_t size) {
1480 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size);
1481 }
1482
1494 template<typename Rep, typename Period>
1496 std::initializer_list<uint16_t> registers,
1497 const uint8_t* buf,
1498 size_t size,
1499 const std::chrono::duration<Rep, Period>& timeout
1500 ) {
1501 write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size, timeout);
1502 }
1503#endif
1504
1513 [[nodiscard]] result<void> try_write_registers(std::span<const uint16_t> registers, std::span<const uint8_t> buf) {
1514 return try_write_registers(registers, buf, DEFAULT_TIMEOUT);
1515 }
1516
1526 template<typename Rep, typename Period>
1528 std::span<const uint16_t> registers,
1529 std::span<const uint8_t> buf,
1530 const std::chrono::duration<Rep, Period>& timeout
1531 ) {
1532 return try_write_registers(registers, buf.data(), buf.size(), timeout);
1533 }
1534
1544 [[nodiscard]] result<void>
1545 try_write_registers(std::span<const uint16_t> registers, const uint8_t* buf, size_t size) {
1546 return try_write_registers(registers, buf, size, DEFAULT_TIMEOUT);
1547 }
1548
1559 template<typename Rep, typename Period>
1561 std::span<const uint16_t> registers,
1562 const uint8_t* buf,
1563 size_t size,
1564 const std::chrono::duration<Rep, Period>& timeout
1565 ) {
1566 return _try_write_registers(registers, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1567 }
1568
1569 // C++23: std::span cannot be constructed from a braced initializer list until C++26 (P2447).
1570 // Remove these overloads when C++26 becomes the minimum standard.
1571
1580 [[nodiscard]] result<void>
1581 try_write_registers(std::initializer_list<uint16_t> registers, std::span<const uint8_t> buf) {
1582 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf);
1583 }
1584
1594 template<typename Rep, typename Period>
1596 std::initializer_list<uint16_t> registers,
1597 std::span<const uint8_t> buf,
1598 const std::chrono::duration<Rep, Period>& timeout
1599 ) {
1600 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, timeout);
1601 }
1602
1612 [[nodiscard]] result<void>
1613 try_write_registers(std::initializer_list<uint16_t> registers, const uint8_t* buf, size_t size) {
1614 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size);
1615 }
1616
1627 template<typename Rep, typename Period>
1629 std::initializer_list<uint16_t> registers,
1630 const uint8_t* buf,
1631 size_t size,
1632 const std::chrono::duration<Rep, Period>& timeout
1633 ) {
1634 return try_write_registers(std::span<const uint16_t>{registers.begin(), registers.size()}, buf, size, timeout);
1635 }
1636
1637#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1649 [[nodiscard]] std::vector<uint8_t> read_register(uint16_t reg, size_t size) {
1650 return unwrap(try_read_register(reg, size));
1651 }
1652
1665 template<typename Rep, typename Period>
1666 [[nodiscard]] std::vector<uint8_t>
1667 read_register(uint16_t reg, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1668 return unwrap(try_read_register(reg, size, timeout));
1669 }
1670
1680 void read_register(uint16_t reg, std::span<uint8_t> buf) { unwrap(try_read_register(reg, buf)); }
1681
1692 template<typename Rep, typename Period>
1693 void read_register(uint16_t reg, std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1694 unwrap(try_read_register(reg, buf, timeout));
1695 }
1696
1707 void read_register(uint16_t reg, uint8_t* buf, size_t size) { unwrap(try_read_register(reg, buf, size)); }
1708
1720 template<typename Rep, typename Period>
1721 void read_register(uint16_t reg, uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1722 unwrap(try_read_register(reg, buf, size, timeout));
1723 }
1724#endif
1725
1734 [[nodiscard]] result<std::vector<uint8_t>> try_read_register(uint16_t reg, size_t size) {
1735 return try_read_register(reg, size, DEFAULT_TIMEOUT);
1736 }
1737
1747 template<typename Rep, typename Period>
1748 [[nodiscard]] result<std::vector<uint8_t>>
1749 try_read_register(uint16_t reg, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1750 std::vector<uint8_t> buf(size);
1751 return try_read_register(reg, buf, timeout).transform([&]() { return buf; });
1752 }
1753
1762 [[nodiscard]] result<void> try_read_register(uint16_t reg, std::span<uint8_t> buf) {
1763 return try_read_register(reg, buf, DEFAULT_TIMEOUT);
1764 }
1765
1774 template<typename Rep, typename Period>
1775 [[nodiscard]] result<void>
1776 try_read_register(uint16_t reg, std::span<uint8_t> buf, const std::chrono::duration<Rep, Period>& timeout) {
1777 return try_read_register(reg, buf.data(), buf.size(), timeout);
1778 }
1779
1789 [[nodiscard]] result<void> try_read_register(uint16_t reg, uint8_t* buf, size_t size) {
1790 return try_read_register(reg, buf, size, DEFAULT_TIMEOUT);
1791 }
1792
1803 template<typename Rep, typename Period>
1804 [[nodiscard]] result<void>
1805 try_read_register(uint16_t reg, uint8_t* buf, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1806 return _try_read_register(reg, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1807 }
1808
1809#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1822 [[nodiscard]] std::vector<uint8_t> read_register(uint8_t high, uint8_t low, size_t size) {
1823 return unwrap(try_read_register(high, low, size));
1824 }
1825
1839 template<typename Rep, typename Period>
1840 [[nodiscard]] std::vector<uint8_t>
1841 read_register(uint8_t high, uint8_t low, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1842 return unwrap(try_read_register(high, low, size, timeout));
1843 }
1844
1856 void read_register(uint8_t high, uint8_t low, uint8_t* buf, size_t size) {
1857 unwrap(try_read_register(high, low, buf, size));
1858 }
1859
1872 template<typename Rep, typename Period>
1874 uint8_t high,
1875 uint8_t low,
1876 uint8_t* buf,
1877 size_t size,
1878 const std::chrono::duration<Rep, Period>& timeout
1879 ) {
1880 unwrap(try_read_register(high, low, buf, size, timeout));
1881 }
1882#endif
1883
1893 [[nodiscard]] result<std::vector<uint8_t>> try_read_register(uint8_t high, uint8_t low, size_t size) {
1894 return try_read_register(high, low, size, DEFAULT_TIMEOUT);
1895 }
1896
1907 template<typename Rep, typename Period>
1908 [[nodiscard]] result<std::vector<uint8_t>>
1909 try_read_register(uint8_t high, uint8_t low, size_t size, const std::chrono::duration<Rep, Period>& timeout) {
1910 std::vector<uint8_t> buf(size);
1911 return try_read_register(high, low, buf, timeout).transform([&]() { return buf; });
1912 }
1913
1923 [[nodiscard]] result<void> try_read_register(uint8_t high, uint8_t low, std::span<uint8_t> buf) {
1924 return try_read_register(high, low, buf, DEFAULT_TIMEOUT);
1925 }
1926
1937 template<typename Rep, typename Period>
1939 uint8_t high,
1940 uint8_t low,
1941 std::span<uint8_t> buf,
1942 const std::chrono::duration<Rep, Period>& timeout
1943 ) {
1944 return try_read_register(high, low, buf.data(), buf.size(), timeout);
1945 }
1946
1957 [[nodiscard]] result<void> try_read_register(uint8_t high, uint8_t low, uint8_t* buf, size_t size) {
1958 return try_read_register(high, low, buf, size, DEFAULT_TIMEOUT);
1959 }
1960
1972 template<typename Rep, typename Period>
1974 uint8_t high,
1975 uint8_t low,
1976 uint8_t* buf,
1977 size_t size,
1978 const std::chrono::duration<Rep, Period>& timeout
1979 ) {
1980 return _try_read_register(high, low, buf, size, std::chrono::ceil<std::chrono::milliseconds>(timeout));
1981 }
1982
1983private:
1984 explicit master_device(master_bus* bus, i2c_master_dev_handle_t handle, uint16_t address);
1985
1986 void _delete() noexcept;
1987
1988 [[nodiscard]] result<void> _try_transmit(const uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
1989 [[nodiscard]] result<void>
1990 _try_multi_buffer_transmit(std::span<const std::span<const uint8_t>> buffers, std::chrono::milliseconds timeout);
1991 [[nodiscard]] result<void> _try_change_address(uint16_t new_address, std::chrono::milliseconds timeout);
1992 [[nodiscard]] result<void>
1993 _try_execute_operations(std::span<const operation> ops, std::chrono::milliseconds timeout);
1994 [[nodiscard]] result<void> _try_receive(uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
1995
1996 [[nodiscard]] result<void>
1997 _try_write_register(uint16_t reg, const uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
1998 [[nodiscard]] result<void>
1999 _try_write_register(uint8_t high, uint8_t low, const uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
2000 [[nodiscard]] result<void> _try_write_registers(
2001 std::span<const uint16_t> registers,
2002 const uint8_t* buf,
2003 size_t size,
2004 std::chrono::milliseconds timeout
2005 );
2006 [[nodiscard]] result<void>
2007 _try_read_register(uint16_t reg, uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
2008 [[nodiscard]] result<void>
2009 _try_read_register(uint8_t high, uint8_t low, uint8_t* buf, size_t size, std::chrono::milliseconds timeout);
2010
2011 master_bus* _bus = nullptr;
2012 i2c_master_dev_handle_t _handle = nullptr;
2013 uint16_t _address = 0;
2014 std::unique_ptr<std::move_only_function<bool() const>> _on_trans_done;
2015};
2016
// end of idfxx_i2c
2018
2019} // namespace idfxx::i2c
2020
2021namespace idfxx {
2022
2030[[nodiscard]] inline std::string to_string(i2c::port p) {
2031 switch (p) {
2032 case i2c::port::i2c0:
2033 return "I2C0";
2034#if SOC_HP_I2C_NUM >= 2
2035 case i2c::port::i2c1:
2036 return "I2C1";
2037#endif
2038#if SOC_LP_I2C_NUM >= 1
2039 case i2c::port::lp_i2c0:
2040 return "LP_I2C0";
2041#endif
2042 default:
2043 return "unknown(" + std::to_string(static_cast<int>(p)) + ")";
2044 }
2045}
2046
2047} // namespace idfxx
2048
2049#include "sdkconfig.h"
2050#ifdef CONFIG_IDFXX_STD_FORMAT
2052#include <algorithm>
2053#include <format>
2054namespace std {
2055template<>
2056struct formatter<idfxx::i2c::port> {
2057 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
2058
2059 template<typename FormatContext>
2060 auto format(idfxx::i2c::port p, FormatContext& ctx) const {
2061 auto s = idfxx::to_string(p);
2062 return std::copy(s.begin(), s.end(), ctx.out());
2063 }
2064};
2065} // namespace std
2067#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:152
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:346
std::vector< uint8_t > scan_devices() const
Scans for devices on the bus.
Definition master.hpp:297
enum port port() const
Returns the I2C port.
Definition master.hpp:285
std::vector< uint8_t > scan_devices(const std::chrono::duration< Rep, Period > &timeout) const
Scans for devices on the bus.
Definition master.hpp:309
void probe(uint16_t address, const std::chrono::duration< Rep, Period > &timeout) const
Probes for a device at the specified address.
Definition master.hpp:334
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:374
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:357
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:282
freq::hertz frequency() const
Returns the bus clock frequency in Hz.
Definition master.hpp:288
void unlock() const
Releases exclusive access to the bus.
Definition master.hpp:274
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:266
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:322
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:390
void lock() const
Acquires exclusive access to the bus.
Definition master.hpp:258
master_bus & operator=(master_bus &&other) noexcept
I2C device at a specific address with register operations.
Definition master.hpp:420
void transmit(const uint8_t *buf, size_t size)
Transmits data to the device.
Definition master.hpp:668
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:1560
result< void > try_probe() const
Probes the device.
Definition master.hpp:563
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:1805
void read_register(uint8_t high, uint8_t low, uint8_t *buf, size_t size)
Reads data from a register.
Definition master.hpp:1856
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:1391
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:1213
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:1051
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:1495
void write_register(uint8_t high, uint8_t low, std::span< const uint8_t > buf)
Writes data to a register.
Definition master.hpp:1233
result< void > try_execute_operations(std::span< const operation > ops)
Executes a custom sequence of I2C operations.
Definition master.hpp:934
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:1157
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:1527
void write_register(uint16_t reg, const uint8_t *buf, size_t size)
Writes data to a register.
Definition master.hpp:1142
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:1321
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:1249
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:1667
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:1734
void register_event_callbacks(std::move_only_function< bool() const > on_trans_done)
Registers a callback for transaction-done events.
Definition master.hpp:862
void write_registers(std::initializer_list< uint16_t > registers, std::span< const uint8_t > buf)
Writes data to multiple registers.
Definition master.hpp:1446
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:1595
void write_register(uint16_t reg, std::span< const uint8_t > buf)
Writes data to a register.
Definition master.hpp:1115
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:1973
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:1693
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:1613
void write_registers(std::span< const uint16_t > registers, const uint8_t *buf, size_t size)
Writes data to multiple registers.
Definition master.hpp:1409
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:1356
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:1545
result< void > try_read_register(uint16_t reg, std::span< uint8_t > buf)
Reads data from a register.
Definition master.hpp:1762
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:1340
void transmit(std::span< const uint8_t > data, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
Definition master.hpp:637
void receive(uint8_t *buf, size_t size)
Receives data from the device.
Definition master.hpp:990
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:542
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:1957
void receive(uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:1003
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:1079
void probe(const std::chrono::duration< Rep, Period > &timeout) const
Probes the device.
Definition master.hpp:553
result< std::vector< uint8_t > > try_receive(size_t size)
Receives data from the device.
Definition master.hpp:1039
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:1306
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:1893
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:1909
void execute_operations(std::span< const operation > ops)
Executes a custom sequence of I2C operations.
Definition master.hpp:907
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:755
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:1873
result< void > try_read_register(uint8_t high, uint8_t low, std::span< uint8_t > buf)
Reads data from a register.
Definition master.hpp:1923
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:1822
result< void > try_transmit(Buffers... buffers)
Transmits data from multiple buffers in a single I2C transaction.
Definition master.hpp:709
result< void > try_write_register(uint16_t reg, std::span< const uint8_t > buf)
Writes data to a register.
Definition master.hpp:1170
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:1628
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:1185
void transmit(std::span< const uint8_t > data)
Transmits data to the device.
Definition master.hpp:589
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:1376
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:1479
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:1128
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:724
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:1749
uint16_t address() const
Returns the device address.
Definition master.hpp:533
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:1938
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:1721
result< void > try_transmit(const uint8_t *buf, size_t size)
Transmits data to the device.
Definition master.hpp:767
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:1286
void change_address(uint16_t new_address)
Changes the I2C address used for subsequent operations.
Definition master.hpp:798
result< void > try_receive(std::span< uint8_t > buf, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:1101
result< void > try_receive(uint8_t *buf, size_t size)
Receives data from the device.
Definition master.hpp:1064
i2c_master_dev_handle_t handle() const
Returns the underlying ESP-IDF device handle.
Definition master.hpp:530
void read_register(uint16_t reg, std::span< uint8_t > buf)
Reads data from a register.
Definition master.hpp:1680
void transmit(std::span< const std::span< const uint8_t > > buffers)
Transmits data from multiple buffers in a single I2C transaction.
Definition master.hpp:625
void transmit(const uint8_t *buf, size_t size, const std::chrono::duration< Rep, Period > &timeout)
Transmits data to the device.
Definition master.hpp:681
result< void > try_write_register(uint16_t reg, const uint8_t *buf, size_t size)
Writes data to a register.
Definition master.hpp:1198
result< void > try_receive(std::span< uint8_t > buf)
Receives data from the device.
Definition master.hpp:1090
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:1841
result< void > try_read_register(uint16_t reg, uint8_t *buf, size_t size)
Reads data from a register.
Definition master.hpp:1789
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:782
result< void > try_transmit(std::span< const uint8_t > data)
Transmits data to the device.
Definition master.hpp:693
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:1461
std::vector< uint8_t > receive(size_t size)
Receives data from the device.
Definition master.hpp:963
std::vector< uint8_t > read_register(uint16_t reg, size_t size)
Reads data from a register.
Definition master.hpp:1649
result< void > try_change_address(uint16_t new_address)
Changes the I2C address used for subsequent operations.
Definition master.hpp:828
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:948
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:1513
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:738
std::vector< uint8_t > receive(size_t size, const std::chrono::duration< Rep, Period > &timeout)
Receives data from the device.
Definition master.hpp:977
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:1581
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:1269
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:655
result< void > try_probe(const std::chrono::duration< Rep, Period > &timeout) const
Probes the device.
Definition master.hpp:573
void receive(std::span< uint8_t > buf)
Receives data from the device.
Definition master.hpp:1015
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:1425
void read_register(uint16_t reg, uint8_t *buf, size_t size)
Reads data from a register.
Definition master.hpp:1707
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:845
master_bus & bus() const
Returns the parent bus.
Definition master.hpp:524
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:813
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:919
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:1776
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:1027
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
Definition adc.hpp:48
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:169
freq::hertz frequency
Clock frequency in Hz.
Definition master.hpp:172
bool allow_pd
Allow powering down the bus during light sleep.
Definition master.hpp:181
idfxx::gpio scl
GPIO pin for the SCL line.
Definition master.hpp:171
idfxx::gpio sda
GPIO pin for the SDA line.
Definition master.hpp:170
size_t trans_queue_depth
Depth of internal transfer queue for asynchronous transactions.
Definition master.hpp:179
uint8_t glitch_ignore_cnt
Glitch filter count (0-7). Higher values filter more noise.
Definition master.hpp:177
bool enable_internal_pullup
Enable internal pull-up resistors on SDA and SCL.
Definition master.hpp:180
I2C device configuration.
Definition master.hpp:434
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