1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
// Copyright 2025 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <stdint.h>
/**
* \file
*
* \defgroup i2c_master I2C Master API
*
* \brief API to communicate with I2C devices.
* \{
*/
typedef int16_t i2c_status_t;
#define I2C_STATUS_SUCCESS (0)
#define I2C_STATUS_ERROR (-1)
#define I2C_STATUS_TIMEOUT (-2)
#define I2C_TIMEOUT_IMMEDIATE (0)
#define I2C_TIMEOUT_INFINITE (0xFFFF)
/**
* \brief Initialize the I2C driver. This function must be called only once, before any of the below functions can be called.
*
* This function is weakly defined, meaning it can be overridden if necessary for your particular use case.
*/
void i2c_init(void);
/**
* \brief Send multiple bytes to the selected I2C device.
*
* \param address The 7-bit I2C address of the device.
* \param data A pointer to the data to transmit.
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
#if defined(__AVR__) || defined(__DOXYGEN__)
/**
* \brief Send multiple bytes from PROGMEM to the selected I2C device.
*
* On ARM devices, this function is simply an alias for i2c_transmit(address, data, length, timeout).
*
* \param address The 7-bit I2C address of the device.
* \param data A pointer to the data to transmit.
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
#else
# define i2c_transmit_P(address, data, length, timeout) i2c_transmit(address, data, length, timeout)
#endif
/**
* \brief Receive multiple bytes from the selected I2C device.
*
* \param address The 7-bit I2C address of the device.
* \param data A pointer to a buffer to read into.
* \param length The number of bytes to read. Take care not to overrun the length of `data`.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
/**
* \brief Write to a register with an 8-bit address on the I2C device.
*
* \param devaddr The 7-bit I2C address of the device.
* \param regaddr The register address to write to.
* \param data A pointer to the data to transmit.
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_write_register(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
/**
* \brief Write to a register with a 16-bit address (big endian) on the I2C device.
*
* \param devaddr The 7-bit I2C address of the device.
* \param regaddr The register address to write to.
* \param data A pointer to the data to transmit.
* \param length The number of bytes to write. Take care not to overrun the length of `data`.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_write_register16(uint8_t devaddr, uint16_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
/**
* \brief Read from a register with an 8-bit address on the I2C device.
*
* \param devaddr The 7-bit I2C address of the device.
* \param regaddr The register address to read from.
* \param data A pointer to a buffer to read into.
* \param length The number of bytes to read. Take care not to overrun the length of `data`.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_read_register(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
/**
* \brief Read from a register with a 16-bit address (big endian) on the I2C device.
*
* \param devaddr The 7-bit I2C address of the device.
* \param regaddr The register address to read from.
* \param data A pointer to a buffer to read into.
* \param length The number of bytes to read. Take care not to overrun the length of `data`.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_read_register16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
/**
* \brief Ping the I2C bus for a specific address.
*
* On ChibiOS a "best effort" attempt is made by reading a single byte from register 0 at the given address. This should generally work except for I2C devices that do not not respond to a register 0 read request, which will result in a false negative result (unsuccessful response to ping attempt).
*
* This function is weakly defined, meaning it can be overridden if necessary for your particular use case.
*
* \param address The 7-bit I2C address of the device.
* \param timeout The time in milliseconds to wait for a response from the target device.
*
* \return `I2C_STATUS_TIMEOUT` if the timeout period elapses, `I2C_STATUS_ERROR` if some other error occurs, otherwise `I2C_STATUS_SUCCESS`.
*/
i2c_status_t i2c_ping_address(uint8_t address, uint16_t timeout);
/** \} */
|