5
5
*/
6
6
7
7
#include < Wire.h>
8
+ #include < stddef.h>
8
9
#include < zephyr/sys/util_macro.h>
9
10
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 );
12
55
}
13
56
14
57
void arduino::ZephyrI2C::begin () {
15
- ring_buf_init (&rxRingBuffer. rb , sizeof (rxRingBuffer. buffer ), rxRingBuffer. buffer );
58
+
16
59
}
17
60
18
61
void arduino::ZephyrI2C::begin (uint8_t slaveAddr) {
19
-
62
+ i2c_cfg.address = slaveAddr;
63
+ i2c_cfg.callbacks = &target_callbacks;
64
+
65
+ // Register I2C target
66
+ i2c_target_register (i2c_dev, &i2c_cfg);
20
67
}
21
68
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
+ }
23
76
24
77
void 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) {
48
94
_address = address;
49
- usedTxBuffer = 0 ;
95
+ ring_buf_reset (&txRingBuffer.rb );
96
+ ring_buf_reset (&rxRingBuffer.rb );
50
97
}
51
98
52
99
uint8_t arduino::ZephyrI2C::endTransmission (bool stopBit) {
53
- int ret = i2c_write (i2c_dev, txBuffer, usedTxBuffer, _address);
54
- if (ret) {
55
- return 1 ; // fail
100
+ int ret = 0 ;
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
+ if (len && buf) {
106
+ ret = i2c_write (i2c_dev, buf, len, _address);
56
107
}
57
- return 0 ;
108
+
109
+ // Must be called even if 0 bytes claimed.
110
+ ring_buf_get_finish (&txRingBuffer.rb , len);
111
+
112
+ return ret ? 1 : 0 ;
58
113
}
59
114
60
- uint8_t arduino::ZephyrI2C::endTransmission (void ) { // TODO for ADS1115
115
+ uint8_t arduino::ZephyrI2C::endTransmission (void ) {
61
116
return endTransmission (true );
62
117
}
63
118
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 ;
119
+ size_t arduino::ZephyrI2C::requestFrom (uint8_t address, size_t len, bool stopBit) {
120
+ int ret = 0 ;
121
+ uint8_t *buf = NULL ;
122
+ len = ring_buf_put_claim (&rxRingBuffer.rb , &buf, len);
123
+
124
+ if (len && buf) {
125
+ ret = i2c_read (i2c_dev, buf, len, address);
76
126
}
77
- return len;
127
+
128
+ // Must be called even if 0 bytes claimed.
129
+ ring_buf_put_finish (&rxRingBuffer.rb , len);
130
+
131
+ return ret ? 1 : 0 ;
78
132
}
79
133
80
- size_t arduino::ZephyrI2C::requestFrom (uint8_t address, size_t len) { // TODO for ADS1115
134
+ size_t arduino::ZephyrI2C::requestFrom (uint8_t address, size_t len) {
81
135
return requestFrom (address, len, true );
82
136
}
83
137
84
- size_t arduino::ZephyrI2C::write (uint8_t data) { // TODO for ADS1115
85
- txBuffer[usedTxBuffer++] = data;
86
- return 1 ;
138
+ size_t arduino::ZephyrI2C::write (uint8_t data) {
139
+ return ring_buf_put (&txRingBuffer.rb , &data, 1 );
87
140
}
88
141
89
142
size_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;
143
+ return ring_buf_put (&txRingBuffer.rb , buffer, size);
96
144
}
97
145
98
146
int arduino::ZephyrI2C::read () {
99
147
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 ];
148
+ if (available ()) {
149
+ if (ring_buf_get (&rxRingBuffer.rb , buf, 1 )) {
150
+ return (int ) buf[0 ];
151
+ }
106
152
}
107
153
return -1 ;
108
154
}
@@ -113,17 +159,73 @@ int arduino::ZephyrI2C::available() {
113
159
114
160
int arduino::ZephyrI2C::peek () {
115
161
uint8_t buf[1 ];
116
- int bytes_read = ring_buf_peek (&rxRingBuffer.rb , buf, 1 );
117
- if (bytes_read == 0 ){
118
- return 0 ;
162
+ if (!ring_buf_peek (&rxRingBuffer.rb , buf, 1 )) {
163
+ return -1 ;
119
164
}
120
- return (int )buf[0 ];
165
+ return (int ) buf[0 ];
121
166
}
122
167
123
- void arduino::ZephyrI2C::flush () {}
168
+ void arduino::ZephyrI2C::flush () {
124
169
125
- void arduino::ZephyrI2C::onReceive (voidFuncPtrParamInt cb) {}
126
- void arduino::ZephyrI2C::onRequest (voidFuncPtr cb) {}
170
+ }
171
+
172
+ void arduino::ZephyrI2C::onReceive (voidFuncPtrParamInt cb) {
173
+ onReceiveCb = cb;
174
+ }
175
+
176
+ void arduino::ZephyrI2C::onRequest (voidFuncPtr cb) {
177
+ onRequestCb = cb;
178
+ }
179
+
180
+ int arduino::ZephyrI2C::writeRequestedCallback (struct i2c_target_config *config) {
181
+ // Reset the buffer on write requests.
182
+ ring_buf_reset (&rxRingBuffer.rb );
183
+ return 0 ;
184
+ }
185
+
186
+ int arduino::ZephyrI2C::writeReceivedCallback (struct i2c_target_config *config, uint8_t val) {
187
+ size_t len = ring_buf_size_get (&rxRingBuffer.rb );
188
+ size_t max = ring_buf_capacity_get (&rxRingBuffer.rb );
189
+
190
+ // If the buffer is about to overflow, invoke the callback
191
+ // with the current length.
192
+ if (onReceiveCb && ((len + 1 ) > max)) {
193
+ onReceiveCb (len);
194
+ }
195
+
196
+ return ring_buf_put (&rxRingBuffer.rb , &val, 1 ) ? 0 : -1 ;
197
+ }
198
+
199
+ int arduino::ZephyrI2C::readRequestedCallback (struct i2c_target_config *config, uint8_t *val) {
200
+ // Reset the buffer on read requests.
201
+ ring_buf_reset (&txRingBuffer.rb );
202
+
203
+ if (onRequestCb) {
204
+ onRequestCb ();
205
+ }
206
+
207
+ return readProcessedCallback (config, val);
208
+ }
209
+
210
+ int arduino::ZephyrI2C::readProcessedCallback (struct i2c_target_config *config, uint8_t *val) {
211
+ *val = 0xFF ;
212
+ ring_buf_get (&txRingBuffer.rb , val, 1 );
213
+ // Returning a negative value here is not handled gracefully and
214
+ // causes the target/board to stop responding (at least with ST).
215
+ return 0 ;
216
+ }
217
+
218
+ int arduino::ZephyrI2C::stopCallback (struct i2c_target_config *config) {
219
+ // If the RX buffer is not empty invoke the callback with the
220
+ // remaining data length.
221
+ if (onReceiveCb) {
222
+ size_t len = ring_buf_size_get (&rxRingBuffer.rb );
223
+ if (len) {
224
+ onReceiveCb (len);
225
+ }
226
+ }
227
+ return 0 ;
228
+ }
127
229
128
230
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), i2cs)
129
231
#if (DT_PROP_LEN(DT_PATH(zephyr_user), i2cs) > 1)
0 commit comments