Skip to content

Commit c892489

Browse files
committed
libraries/Wire: Multiple instance support.
Signed-off-by: IFX-Anusha <[email protected]>
1 parent c460332 commit c892489

File tree

2 files changed

+181
-107
lines changed

2 files changed

+181
-107
lines changed

libraries/Wire/Wire.cpp

Lines changed: 134 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,48 @@ extern "C" {
77
#include "Wire.h"
88

99
#define I2C_DEFAULT_FREQ 100000
10+
#define MAX_I2C_INSTANCES 10
1011

11-
TwoWire::TwoWire(cyhal_gpio_t sda, cyhal_gpio_t scl) : sda_pin(sda), scl_pin(scl) {
12+
TwoWire *TwoWire::instances[MAX_I2C_INSTANCES] = {nullptr};
13+
cyhal_i2c_t TwoWire::i2c_objs[MAX_I2C_INSTANCES];
14+
15+
TwoWire::TwoWire(cyhal_gpio_t sda, cyhal_gpio_t scl, uint8_t instance) : sda_pin(sda), scl_pin(scl), instance(instance) {
16+
if (instance < MAX_I2C_INSTANCES) {
17+
instances[instance] = this;
18+
}
1219
}
1320

1421
void TwoWire::_begin() {
15-
1622
rxBufferIndex = 0;
1723
rxBufferLength = 0;
1824

1925
txBufferIndex = 0;
2026
txBufferLength = 0;
2127

2228
if (is_master) {
23-
i2c_config= {
24-
.is_slave = is_master ? false : true,
25-
0,
29+
i2c_config = {
30+
.is_slave = CYHAL_I2C_MODE_MASTER,
31+
.address = 0,
2632
.frequencyhal_hz = I2C_DEFAULT_FREQ
2733
};
28-
}
29-
else {
34+
} else {
3035
i2c_config = {
31-
.is_slave = is_master ? false : true,
32-
slave_address,
36+
.is_slave = CYHAL_I2C_MODE_SLAVE,
37+
.address = slave_address,
3338
.frequencyhal_hz = I2C_DEFAULT_FREQ
3439
};
3540
}
36-
cyhal_i2c_init(&i2c_obj, sda_pin, scl_pin, NULL);
37-
cyhal_i2c_configure(&i2c_obj, &i2c_config);
38-
cyhal_i2c_register_callback(&i2c_obj, i2c_event_handler, this);
41+
42+
cyhal_i2c_init(&i2c_objs[instance], sda_pin, scl_pin, NULL);
43+
cyhal_i2c_configure(&i2c_objs[instance], &i2c_config);
44+
45+
if (!is_master) {
46+
// Configure the read and write buffers for the I2C slave
47+
cyhal_i2c_slave_config_read_buffer(&i2c_objs[instance], rxBuffer, BUFFER_LENGTH);
48+
cyhal_i2c_slave_config_write_buffer(&i2c_objs[instance], txBuffer, BUFFER_LENGTH);
49+
}
50+
51+
cyhal_i2c_register_callback(&i2c_objs[instance], i2c_event_handler, this);
3952
}
4053

4154
void TwoWire::begin() {
@@ -60,57 +73,123 @@ void TwoWire::begin(uint8_t address) {
6073
}
6174

6275
void TwoWire::end() {
63-
cyhal_i2c_free(&i2c_obj);
76+
cyhal_i2c_free(&i2c_objs[instance]);
6477
}
6578

6679
void TwoWire::setClock(uint32_t freq) {
67-
if(is_master) {
80+
if (is_master) {
6881
i2c_config = {
6982
.is_slave = false,
70-
0,
83+
.address = 0,
7184
.frequencyhal_hz = freq
7285
};
73-
}
74-
else {
86+
} else {
7587
i2c_config = {
7688
.is_slave = true,
77-
slave_address,
89+
.address = slave_address,
7890
.frequencyhal_hz = freq
7991
};
8092
}
81-
cyhal_i2c_configure(&i2c_obj, &i2c_config);
93+
cyhal_i2c_configure(&i2c_objs[instance], &i2c_config);
8294
}
8395

84-
void TwoWire:: beginTransmission(uint8_t address) {
96+
void TwoWire::beginTransmission(uint8_t address) {
8597
txAddress = address;
8698
txBufferIndex = 0;
8799
txBufferLength = 0;
88100
}
89101

90102
uint8_t TwoWire::endTransmission(bool sendStop) {
91-
cy_rslt_t result = cyhal_i2c_master_write(&i2c_obj, slave_address, txBuffer, txBufferLength, timeout, sendStop);
92-
93-
txBufferIndex = 0;
94-
txBufferLength = 0;
103+
cy_rslt_t result;
104+
if (txBufferLength == 0) {
105+
result = cyhal_i2c_master_write(&i2c_objs[instance], txAddress, txBuffer, 0, timeout, sendStop);
106+
if (result != 0xAA2004 && result != 0xAA2005) {
107+
return 1;
108+
} else {
109+
return 0;
110+
}
111+
} else {
112+
result = cyhal_i2c_master_write(&i2c_objs[instance], txAddress, txBuffer, txBufferLength, timeout, sendStop);
113+
txBufferIndex = 0;
114+
txBufferLength = 0;
115+
}
95116

96-
return (result == CY_RSLT_SUCCESS) ? 0 : 1; // Return 0 on success, 1 on failure
117+
if (result != CY_RSLT_SUCCESS) {
118+
// Handle specific error codes
119+
switch (result) {
120+
case 0xAA2004:
121+
Serial.println("Error: No device attached to SDA/SCL, but they are pulled-up.");
122+
break;
123+
case 0xAA2003:
124+
Serial.println("Error: No device attached to SDA/SCL, and they are not pulled-up.");
125+
break;
126+
case CYHAL_I2C_RSLT_ERR_INVALID_PIN:
127+
Serial.println("Error: Invalid pin.");
128+
break;
129+
case CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR:
130+
Serial.println("Error: Cannot reach desired data rate.");
131+
break;
132+
case CYHAL_I2C_RSLT_ERR_INVALID_ADDRESS_SIZE:
133+
Serial.println("Error: Invalid address size.");
134+
break;
135+
case CYHAL_I2C_RSLT_ERR_TX_RX_BUFFERS_ARE_EMPTY:
136+
Serial.println("Error: TX/RX buffers are empty.");
137+
break;
138+
case CYHAL_I2C_RSLT_ERR_PREVIOUS_ASYNCH_PENDING:
139+
Serial.println("Error: Previous async operation is pending.");
140+
break;
141+
case CYHAL_I2C_RSLT_ERR_PM_CALLBACK:
142+
Serial.println("Error: Failed to register I2C PM callback.");
143+
break;
144+
case CYHAL_I2C_RSLT_ERR_ABORT_ASYNC_TIMEOUT:
145+
Serial.println("Error: Abort async operation timed out.");
146+
break;
147+
case CYHAL_I2C_RSLT_ERR_BAD_ARGUMENT:
148+
Serial.println("Error: Bad argument provided.");
149+
break;
150+
case CYHAL_I2C_RSLT_ERR_UNSUPPORTED:
151+
Serial.println("Error: Unsupported by this device.");
152+
break;
153+
case CYHAL_I2C_RSLT_ERR_NO_ACK:
154+
Serial.println("Error: No ACK received.");
155+
break;
156+
case CYHAL_I2C_RSLT_ERR_CMD_ERROR:
157+
Serial.println("Error: Command error.");
158+
break;
159+
case CYHAL_I2C_RSLT_ERR_BUFFERS_NULL_PTR:
160+
Serial.println("Error: RX or TX buffer is not initialized.");
161+
break;
162+
case CYHAL_I2C_RSLT_WARN_TIMEOUT:
163+
Serial.println("Warning: Timeout.");
164+
break;
165+
case CYHAL_I2C_RSLT_WARN_DEVICE_BUSY:
166+
Serial.println("Warning: Device busy.");
167+
break;
168+
default:
169+
Serial.print("I2C transfer failed with return code: ");
170+
Serial.println(result, HEX);
171+
break;
172+
}
173+
return 1; // Return 1 on failure
174+
}
175+
176+
return 0; // Return 0 on success
97177
}
98178

99179
uint8_t TwoWire::endTransmission(void) {
100180
return endTransmission(true);
101181
}
102182

103183
size_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) {
104-
if(quantity > BUFFER_LENGTH){
184+
if (quantity > BUFFER_LENGTH) {
105185
quantity = BUFFER_LENGTH;
106186
}
107-
cy_rslt_t result = cyhal_i2c_master_read(&i2c_obj, address, rxBuffer, quantity, timeout, stopBit);
108-
if(result == CY_RSLT_SUCCESS){
187+
cy_rslt_t result = cyhal_i2c_master_read(&i2c_objs[instance], address, rxBuffer, quantity, timeout, stopBit);
188+
if (result == CY_RSLT_SUCCESS) {
109189
rxBufferIndex = 0;
110190
rxBufferLength = quantity;
111191
return quantity;
112-
}
113-
else{
192+
} else {
114193
return 0; // Return 0 on failure of read operation
115194
}
116195
}
@@ -120,74 +199,70 @@ size_t TwoWire::requestFrom(uint8_t address, size_t len) {
120199
}
121200

122201
size_t TwoWire::write(uint8_t data) {
123-
/* Check if buffer is full */
124-
if(txBufferLength >= BUFFER_LENGTH){
125-
return 0;
126-
}
202+
/* Check if buffer is full */
203+
if (txBufferLength >= BUFFER_LENGTH) {
204+
return 0;
205+
}
127206

128-
/* Put byte in txBuffer */
129-
txBuffer[txBufferIndex] = data;
130-
txBufferIndex++;
207+
/* Put byte in txBuffer */
208+
txBuffer[txBufferIndex] = data;
209+
txBufferIndex++;
131210

132-
/* Update buffer length */
133-
txBufferLength = txBufferIndex;
134-
135-
return 1;
211+
/* Update buffer length */
212+
txBufferLength = txBufferIndex;
213+
214+
return 1;
136215
}
137216

138217
size_t TwoWire::write(const uint8_t * data, size_t quantity) {
139-
for(size_t i = 0; i < quantity; i++){
140-
write(*(data + i));
141-
}
218+
for (size_t i = 0; i < quantity; i++) {
219+
write(*(data + i));
220+
}
142221

143-
return quantity;
222+
return quantity;
144223
}
145224

146225
int TwoWire::available(void) {
147-
148226
return rxBufferLength - rxBufferIndex;
149227
}
150228

151229
int TwoWire::read(void) {
152-
if(rxBufferIndex < rxBufferLength)
153-
{
230+
if (rxBufferIndex < rxBufferLength) {
154231
return rxBuffer[rxBufferIndex++];
155232
}
156233
return -1;
157234
}
158235

159236
int TwoWire::peek(void) {
160-
if(rxBufferIndex < rxBufferLength)
161-
{
237+
if (rxBufferIndex < rxBufferLength) {
162238
return rxBuffer[rxBufferIndex];
163239
}
164240
return -1;
165241
}
166242

167243
void TwoWire::onReceive(void (*function)(int)) {
168-
user_onReceive = function;
169-
cyhal_i2c_enable_event(&i2c_obj, CYHAL_I2C_SLAVE_READ_EVENT, 7, true);
244+
user_onReceive = function;
245+
cyhal_i2c_enable_event(&i2c_objs[instance], CYHAL_I2C_SLAVE_WRITE_EVENT, 7, true);
170246
}
171247

172248
void TwoWire::onRequest(void (*function)(void)) {
173249
user_onRequest = function;
174-
cyhal_i2c_enable_event(&i2c_obj, CYHAL_I2C_SLAVE_WRITE_EVENT, 7, true);
250+
cyhal_i2c_enable_event(&i2c_objs[instance], CYHAL_I2C_SLAVE_READ_EVENT, 7, true);
175251
}
176252

177253
void TwoWire::i2c_event_handler(void *callback_arg, cyhal_i2c_event_t event) {
178254
TwoWire *instance = static_cast<TwoWire*>(callback_arg);
179-
if (event == CYHAL_I2C_SLAVE_READ_EVENT && instance->user_onReceive) {
255+
if (event == CYHAL_I2C_SLAVE_WRITE_EVENT && instance->user_onReceive) {
180256
instance->user_onReceive(instance->available());
181-
} else if (event == CYHAL_I2C_SLAVE_WRITE_EVENT && instance->user_onRequest) {
257+
} else if (event == CYHAL_I2C_SLAVE_READ_EVENT && instance->user_onRequest) {
182258
instance->user_onRequest();
183259
}
184260
}
185261

186262
#if I2C_HOWNMANY > 0
187-
TwoWire Wire = TwoWire(I2C1_SDA_PIN, I2C1_SCL_PIN);
263+
TwoWire Wire = TwoWire(I2C1_SDA_PIN, I2C1_SCL_PIN, 0);
188264
#endif
189265

190266
#if I2C_HOWNMANY > 1
191-
TwoWire Wire1 = TwoWire(I2C2_SDA_PIN, I2C2_SCL_PIN);
192-
#endif
193-
267+
TwoWire Wire1 = TwoWire(I2C2_SDA_PIN, I2C2_SCL_PIN, 1);
268+
#endif

0 commit comments

Comments
 (0)