55 */
66
77#include < Wire.h>
8+ #include < stddef.h>
89#include < zephyr/sys/util_macro.h>
910
10- arduino::ZephyrI2C::ZephyrI2C (const struct device *i2c) : i2c_dev(i2c)
11- {
11+ // Helper function to get ZephyrI2C instance from config pointer.
12+ static arduino::ZephyrI2C* getInstance (struct i2c_target_config *config) {
13+ return reinterpret_cast <arduino::ZephyrI2C*>(
14+ reinterpret_cast <char *>(config) - offsetof (arduino::ZephyrI2C, i2c_cfg)
15+ );
16+ }
17+
18+ static int i2c_target_stop_cb (struct i2c_target_config *config) {
19+ arduino::ZephyrI2C *instance = getInstance (config);
20+ return instance->stopCallback (config);
21+ }
22+
23+ static int i2c_target_write_requested_cb (struct i2c_target_config *config) {
24+ arduino::ZephyrI2C *instance = getInstance (config);
25+ return instance->writeRequestedCallback (config);
26+ }
27+
28+ static int i2c_target_write_received_cb (struct i2c_target_config *config, uint8_t val) {
29+ arduino::ZephyrI2C *instance = getInstance (config);
30+ return instance->writeReceivedCallback (config, val);
31+ }
32+
33+ static int i2c_target_read_requested_cb (struct i2c_target_config *config, uint8_t *val) {
34+ arduino::ZephyrI2C *instance = getInstance (config);
35+ return instance->readRequestedCallback (config, val);
36+ }
37+
38+ static int i2c_target_read_processed_cb (struct i2c_target_config *config, uint8_t *val) {
39+ arduino::ZephyrI2C *instance = getInstance (config);
40+ return instance->readProcessedCallback (config, val);
41+ }
42+
43+ // I2C target callback structure.
44+ static struct i2c_target_callbacks target_callbacks = {
45+ .write_requested = i2c_target_write_requested_cb,
46+ .read_requested = i2c_target_read_requested_cb,
47+ .write_received = i2c_target_write_received_cb,
48+ .read_processed = i2c_target_read_processed_cb,
49+ .stop = i2c_target_stop_cb,
50+ };
51+
52+ arduino::ZephyrI2C::ZephyrI2C (const struct device *i2c) : i2c_dev(i2c), i2c_cfg({0 }) {
53+ ring_buf_init (&txRingBuffer.rb , sizeof (txRingBuffer.buffer ), txRingBuffer.buffer );
54+ ring_buf_init (&rxRingBuffer.rb , sizeof (rxRingBuffer.buffer ), rxRingBuffer.buffer );
1255}
1356
1457void arduino::ZephyrI2C::begin () {
15- ring_buf_init (&rxRingBuffer. rb , sizeof (rxRingBuffer. buffer ), rxRingBuffer. buffer );
58+
1659}
1760
1861void arduino::ZephyrI2C::begin (uint8_t slaveAddr) {
62+ i2c_cfg.address = slaveAddr;
63+ i2c_cfg.callbacks = &target_callbacks;
1964
65+ // Register I2C target
66+ i2c_target_register (i2c_dev, &i2c_cfg);
2067}
2168
22- void arduino::ZephyrI2C::end () {}
69+ void arduino::ZephyrI2C::end () {
70+ // Unregister I2C target
71+ if (i2c_cfg.address ) {
72+ i2c_target_unregister (i2c_dev, &i2c_cfg);
73+ memset (&i2c_cfg, 0 , sizeof (i2c_cfg));
74+ }
75+ }
2376
2477void arduino::ZephyrI2C::setClock (uint32_t freq) {
25- uint8_t speed = I2C_SPEED_STANDARD;
26- if (freq > 0x06u ) {
27- if (freq == 100000 ) {
28- speed = I2C_SPEED_STANDARD;
29- } else if (freq == 400000 ) {
30- speed = I2C_SPEED_FAST;
31- } else if (freq == 1000000 ) {
32- speed = I2C_SPEED_FAST_PLUS;
33- } else {
34- speed = I2C_SPEED_STANDARD;
35- }
36- } else {
37- speed = (uint8_t ) freq;
38- }
39- uint32_t i2c_cfg = I2C_MODE_CONTROLLER |
40- I2C_SPEED_SET (speed);
41-
42- if (i2c_configure (i2c_dev, i2c_cfg)) {
43- // Serial.println("Failed to configure i2c interface.");
44- }
45- }
46-
47- void arduino::ZephyrI2C::beginTransmission (uint8_t address) { // TODO for ADS1115
78+ uint8_t speed;
79+
80+ if (freq == 100000 ) {
81+ speed = I2C_SPEED_STANDARD;
82+ } else if (freq == 400000 ) {
83+ speed = I2C_SPEED_FAST;
84+ } else if (freq == 1000000 ) {
85+ speed = I2C_SPEED_FAST_PLUS;
86+ } else {
87+ speed = I2C_SPEED_STANDARD;
88+ }
89+
90+ i2c_configure (i2c_dev, I2C_SPEED_SET (speed) | I2C_MODE_CONTROLLER);
91+ }
92+
93+ void arduino::ZephyrI2C::beginTransmission (uint8_t address) {
4894 _address = address;
49- usedTxBuffer = 0 ;
95+ ring_buf_reset (&txRingBuffer.rb );
96+ ring_buf_reset (&rxRingBuffer.rb );
5097}
5198
5299uint8_t arduino::ZephyrI2C::endTransmission (bool stopBit) {
53- int ret = i2c_write (i2c_dev, txBuffer, usedTxBuffer, _address);
54- if (ret) {
55- return 1 ; // fail
56- }
57- return 0 ;
100+ int ret = -EIO;
101+ uint8_t *buf = NULL ;
102+ size_t max = ring_buf_capacity_get (&txRingBuffer.rb );
103+ size_t len = ring_buf_get_claim (&txRingBuffer.rb , &buf, max);
104+
105+ ret = i2c_write (i2c_dev, buf, len, _address);
106+
107+ // Must be called even if 0 bytes claimed.
108+ ring_buf_get_finish (&txRingBuffer.rb , len);
109+
110+ return ret ? 1 : 0 ;
58111}
59112
60- uint8_t arduino::ZephyrI2C::endTransmission (void ) { // TODO for ADS1115
113+ uint8_t arduino::ZephyrI2C::endTransmission (void ) {
61114 return endTransmission (true );
62115}
63116
64- size_t arduino::ZephyrI2C::requestFrom (uint8_t address, size_t len,
65- bool stopBit) {
66- uint8_t buf[len];
67- int ret = i2c_read (i2c_dev, buf, len, address);
68- if (ret != 0 )
69- {
70- return 0 ;
71- }
72- ret = ring_buf_put (&rxRingBuffer.rb , buf, len);
73- if (ret == 0 )
74- {
75- return 0 ;
117+ size_t arduino::ZephyrI2C::requestFrom (uint8_t address, size_t len_in, bool stopBit) {
118+ int ret = -EIO;
119+ uint8_t *buf = NULL ;
120+ size_t len = ring_buf_put_claim (&rxRingBuffer.rb , &buf, len_in);
121+
122+ if (len && buf) {
123+ ret = i2c_read (i2c_dev, buf, len, address);
76124 }
77- return len;
125+
126+ // Must be called even if 0 bytes claimed.
127+ ring_buf_put_finish (&rxRingBuffer.rb , len);
128+
129+ return ret ? 0 : len;
78130}
79131
80- size_t arduino::ZephyrI2C::requestFrom (uint8_t address, size_t len) { // TODO for ADS1115
132+ size_t arduino::ZephyrI2C::requestFrom (uint8_t address, size_t len) {
81133 return requestFrom (address, len, true );
82134}
83135
84- size_t arduino::ZephyrI2C::write (uint8_t data) { // TODO for ADS1115
85- txBuffer[usedTxBuffer++] = data;
86- return 1 ;
136+ size_t arduino::ZephyrI2C::write (uint8_t data) {
137+ return ring_buf_put (&txRingBuffer.rb , &data, 1 );
87138}
88139
89140size_t arduino::ZephyrI2C::write (const uint8_t *buffer, size_t size) {
90- if (usedTxBuffer + size > 256 ) {
91- size = 256 - usedTxBuffer;
92- }
93- memcpy (txBuffer + usedTxBuffer, buffer, size);
94- usedTxBuffer += size;
95- return size;
141+ return ring_buf_put (&txRingBuffer.rb , buffer, size);
96142}
97143
98144int arduino::ZephyrI2C::read () {
99- uint8_t buf[1 ];
100- if (ring_buf_size_get (&rxRingBuffer.rb )) {
101- int ret = ring_buf_get (&rxRingBuffer.rb , buf, 1 );
102- if (ret == 0 ) {
103- return -1 ;
104- }
105- return (int )buf[0 ];
145+ uint8_t buf;
146+ if (ring_buf_get (&rxRingBuffer.rb , &buf, 1 )) {
147+ return (int ) buf;
106148 }
107149 return -1 ;
108150}
@@ -112,18 +154,74 @@ int arduino::ZephyrI2C::available() {
112154}
113155
114156int arduino::ZephyrI2C::peek () {
115- uint8_t buf[1 ];
116- int bytes_read = ring_buf_peek (&rxRingBuffer.rb , buf, 1 );
117- if (bytes_read == 0 ){
118- return 0 ;
157+ uint8_t buf;
158+ if (ring_buf_peek (&rxRingBuffer.rb , &buf, 1 )) {
159+ return (int ) buf;
119160 }
120- return (int )buf[0 ];
161+ return -1 ;
162+ }
163+
164+ void arduino::ZephyrI2C::flush () {
165+
166+ }
167+
168+ void arduino::ZephyrI2C::onReceive (voidFuncPtrParamInt cb) {
169+ onReceiveCb = cb;
170+ }
171+
172+ void arduino::ZephyrI2C::onRequest (voidFuncPtr cb) {
173+ onRequestCb = cb;
174+ }
175+
176+ int arduino::ZephyrI2C::writeRequestedCallback (struct i2c_target_config *config) {
177+ // Reset the buffer on write requests.
178+ ring_buf_reset (&rxRingBuffer.rb );
179+ return 0 ;
180+ }
181+
182+ int arduino::ZephyrI2C::writeReceivedCallback (struct i2c_target_config *config, uint8_t val) {
183+ size_t len = ring_buf_size_get (&rxRingBuffer.rb );
184+ size_t max = ring_buf_capacity_get (&rxRingBuffer.rb );
185+
186+ // If the buffer is about to overflow, invoke the callback
187+ // with the current length.
188+ if (onReceiveCb && ((len + 1 ) > max)) {
189+ onReceiveCb (len);
190+ }
191+
192+ return ring_buf_put (&rxRingBuffer.rb , &val, 1 ) ? 0 : -1 ;
121193}
122194
123- void arduino::ZephyrI2C::flush () {}
195+ int arduino::ZephyrI2C::readRequestedCallback (struct i2c_target_config *config, uint8_t *val) {
196+ // Reset the buffer on read requests.
197+ ring_buf_reset (&txRingBuffer.rb );
198+
199+ if (onRequestCb) {
200+ onRequestCb ();
201+ }
202+
203+ return readProcessedCallback (config, val);
204+ }
124205
125- void arduino::ZephyrI2C::onReceive (voidFuncPtrParamInt cb) {}
126- void arduino::ZephyrI2C::onRequest (voidFuncPtr cb) {}
206+ int arduino::ZephyrI2C::readProcessedCallback (struct i2c_target_config *config, uint8_t *val) {
207+ *val = 0xFF ;
208+ ring_buf_get (&txRingBuffer.rb , val, 1 );
209+ // Returning a negative value here is not handled gracefully and
210+ // causes the target/board to stop responding (at least with ST).
211+ return 0 ;
212+ }
213+
214+ int arduino::ZephyrI2C::stopCallback (struct i2c_target_config *config) {
215+ // If the RX buffer is not empty invoke the callback with the
216+ // remaining data length.
217+ if (onReceiveCb) {
218+ size_t len = ring_buf_size_get (&rxRingBuffer.rb );
219+ if (len) {
220+ onReceiveCb (len);
221+ }
222+ }
223+ return 0 ;
224+ }
127225
128226#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), i2cs)
129227#if (DT_PROP_LEN(DT_PATH(zephyr_user), i2cs) > 1)
0 commit comments