Skip to content

Commit 887fe87

Browse files
committed
Reworked Wire library
- implemented two classes, one support only I2C master role, fully non-static with independent instances, second implementing both master and slave roles, always using the same static TWI singleton class from core - classes implementing both mods can be always used directly via names TwoWireMaster and TwoWireMasterOrSlave, however that's not a recommand use for portable code/libraries! - mode (the behaviour or TwoWire class) can be switched from default/compatible master-or-slave to master-only via TWOWIRE_MASTER_ONLY define - support for optional global Wire instance in both modes - master-only and master-or-slave modes can used together in some project by splitting code into separate compilation units
1 parent 79532ba commit 887fe87

File tree

2 files changed

+271
-46
lines changed

2 files changed

+271
-46
lines changed

libraries/Wire/Wire.cpp

Lines changed: 186 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -38,113 +38,132 @@ extern "C" {
3838
#error Wire library is not supported on this board
3939
#endif
4040

41+
// Private Methods /////////////////////////////////////////////////////////////
4142
// Constructors ////////////////////////////////////////////////////////////////
4243

43-
TwoWire::TwoWire(uint8_t rxBufferSize, uint8_t txBufferSize) :
44-
rxBuffer{new uint8_t[rxBufferSize]},
45-
txBuffer{new uint8_t[txBufferSize]}
44+
TwoWireBase::TwoWireBase(uint8_t rxBufferSize, uint8_t txBufferSize) :
45+
twiMaster{new TwiMaster},
46+
rxBufferSize{rxBufferSize},
47+
rxBuffer{new uint8_t[rxBufferSize]},
48+
txBufferSize{txBufferSize},
49+
txBuffer{new uint8_t[txBufferSize]}
4650
{
47-
this->txBufferSize = txBufferSize;
48-
this->rxBufferSize = rxBufferSize;
4951
}
5052

51-
// Public Methods //////////////////////////////////////////////////////////////
53+
TwoWireBase::TwoWireBase(TwiMaster* twiPtr, uint8_t rxBufferSize, uint8_t txBufferSize, uint8_t* rxBuffer, uint8_t* txBuffer) :
54+
twiMaster{twiPtr},
55+
rxBufferSize{rxBufferSize},
56+
rxBuffer{rxBuffer},
57+
txBufferSize{txBufferSize},
58+
txBuffer{txBuffer}
59+
{
60+
}
5261

53-
void TwoWire::begin(int sda, int scl)
62+
inline TwiMaster& TwoWireBase::getTwiMaster()
5463
{
55-
twi.init(sda, scl);
56-
flush();
64+
return *twiMaster;
5765
}
66+
inline void TwoWireBase::releaseTwiMaster()
67+
{
68+
twiMaster.release();
69+
}
70+
71+
// Public Methods //////////////////////////////////////////////////////////////
5872

59-
void TwoWire::pins(int sda, int scl)
73+
void TwoWireBase::begin(int sda, int scl)
6074
{
75+
lastSdaPin = sda;
76+
lastSclPin = scl;
77+
getTwiMaster().init(sda, scl);
78+
flush();
6179
}
6280

63-
void TwoWire::begin(void)
81+
void TwoWireBase::begin(void)
6482
{
65-
begin(SDA, SCL);
83+
begin(lastSdaPin, lastSclPin);
6684
}
6785

68-
uint8_t TwoWire::status()
86+
void TwoWireBase::pins(int sda, int scl)
6987
{
70-
return twi.status();
88+
lastSdaPin = sda;
89+
lastSclPin = scl;
7190
}
7291

73-
void TwoWire::begin(int address)
92+
uint8_t TwoWireBase::status()
7493
{
75-
begin((uint8_t)address);
94+
return getTwiMaster().status();
7695
}
7796

78-
void TwoWire::setClock(uint32_t frequency)
97+
void TwoWireBase::setClock(uint32_t frequency)
7998
{
80-
twi.setClock(frequency);
99+
getTwiMaster().setClock(frequency);
81100
}
82101

83-
void TwoWire::setClockStretchLimit(uint32_t limit)
102+
void TwoWireBase::setClockStretchLimit(uint32_t limit)
84103
{
85-
twi.setClockStretchLimit(limit);
104+
getTwiMaster().setClockStretchLimit(limit);
86105
}
87106

88-
size_t TwoWire::requestFrom(uint8_t address, size_t size, bool sendStop)
107+
size_t TwoWireBase::requestFrom(uint8_t address, size_t size, bool sendStop)
89108
{
90109
if (size > rxBufferSize)
91110
{
92111
size = rxBufferSize;
93112
}
94-
size_t read = (twi.readFrom(address, rxBuffer.get(), size, sendStop) == 0) ? size : 0;
113+
size_t read = (getTwiMaster().readFrom(address, rxBuffer.get(), size, sendStop) == 0) ? size : 0;
95114
rxBufferIndex = 0;
96115
rxBufferLength = read;
97116
return read;
98117
}
99118

100-
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
119+
uint8_t TwoWireBase::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
101120
{
102121
return requestFrom(address, static_cast<size_t>(quantity), static_cast<bool>(sendStop));
103122
}
104123

105-
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
124+
uint8_t TwoWireBase::requestFrom(uint8_t address, uint8_t quantity)
106125
{
107126
return requestFrom(address, static_cast<size_t>(quantity), true);
108127
}
109128

110-
uint8_t TwoWire::requestFrom(int address, int quantity)
129+
uint8_t TwoWireBase::requestFrom(int address, int quantity)
111130
{
112131
return requestFrom(static_cast<uint8_t>(address), static_cast<size_t>(quantity), true);
113132
}
114133

115-
uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
134+
uint8_t TwoWireBase::requestFrom(int address, int quantity, int sendStop)
116135
{
117136
return requestFrom(static_cast<uint8_t>(address), static_cast<size_t>(quantity), static_cast<bool>(sendStop));
118137
}
119138

120-
void TwoWire::beginTransmission(uint8_t address)
139+
void TwoWireBase::beginTransmission(uint8_t address)
121140
{
122141
transmitting = 1;
123142
txAddress = address;
124143
txBufferIndex = 0;
125144
txBufferLength = 0;
126145
}
127146

128-
void TwoWire::beginTransmission(int address)
147+
void TwoWireBase::beginTransmission(int address)
129148
{
130149
beginTransmission((uint8_t)address);
131150
}
132151

133-
uint8_t TwoWire::endTransmission(uint8_t sendStop)
152+
uint8_t TwoWireBase::endTransmission(uint8_t sendStop)
134153
{
135-
int8_t ret = twi.writeTo(txAddress, txBuffer.get(), txBufferLength, sendStop);
154+
int8_t ret = getTwiMaster().writeTo(txAddress, txBuffer.get(), txBufferLength, sendStop);
136155
txBufferIndex = 0;
137156
txBufferLength = 0;
138157
transmitting = 0;
139158
return ret;
140159
}
141160

142-
uint8_t TwoWire::endTransmission(void)
161+
uint8_t TwoWireBase::endTransmission(void)
143162
{
144163
return endTransmission(true);
145164
}
146165

147-
size_t TwoWire::write(uint8_t data)
166+
size_t TwoWireBase::write(uint8_t data)
148167
{
149168
if (transmitting)
150169
{
@@ -165,7 +184,7 @@ size_t TwoWire::write(uint8_t data)
165184
return 1;
166185
}
167186

168-
size_t TwoWire::write(const uint8_t *data, size_t quantity)
187+
size_t TwoWireBase::write(const uint8_t *data, size_t quantity)
169188
{
170189
if (transmitting)
171190
{
@@ -185,7 +204,7 @@ size_t TwoWire::write(const uint8_t *data, size_t quantity)
185204
return quantity;
186205
}
187206

188-
int TwoWire::available(void)
207+
int TwoWireBase::available(void)
189208
{
190209
int result = rxBufferLength - rxBufferIndex;
191210

@@ -199,7 +218,7 @@ int TwoWire::available(void)
199218
return result;
200219
}
201220

202-
int TwoWire::read(void)
221+
int TwoWireBase::read(void)
203222
{
204223
int value = -1;
205224
if (rxBufferIndex < rxBufferLength)
@@ -210,7 +229,7 @@ int TwoWire::read(void)
210229
return value;
211230
}
212231

213-
int TwoWire::peek(void)
232+
int TwoWireBase::peek(void)
214233
{
215234
int value = -1;
216235
if (rxBufferIndex < rxBufferLength)
@@ -220,16 +239,144 @@ int TwoWire::peek(void)
220239
return value;
221240
}
222241

223-
void TwoWire::flush(void)
242+
void TwoWireBase::flush(void)
224243
{
225244
rxBufferIndex = 0;
226245
rxBufferLength = 0;
227246
txBufferIndex = 0;
228247
txBufferLength = 0;
229248
}
230249

231-
// Preinstantiate Objects //////////////////////////////////////////////////////
250+
// Master-only Constructors ////////////////////////////////////////////////////
251+
252+
TwoWireMaster::TwoWireMaster(uint8_t rxBufferSize, uint8_t txBufferSize)
253+
: TwoWireBase(rxBufferSize, txBufferSize)
254+
{}
232255

256+
TwoWireMaster::TwoWireMaster(uint8_t rxBufferSize, uint8_t txBufferSize, uint8_t* rxBuffer, uint8_t* txBuffer)
257+
: TwoWireBase(new TwiMaster{}, rxBufferSize, txBufferSize, rxBuffer, txBuffer)
258+
{}
259+
260+
// Master-or-Slave Constructors ////////////////////////////////////////////////
261+
262+
TwoWireMasterOrSlave::TwoWireMasterOrSlave(uint8_t rxBufferSize, uint8_t txBufferSize, uint8_t* rxBuffer, uint8_t* txBuffer)
263+
: TwoWireBase(&twiMasterSingleton, rxBufferSize, txBufferSize, rxBuffer, txBuffer)
264+
{}
265+
266+
TwoWireMasterOrSlave::~TwoWireMasterOrSlave()
267+
{
268+
releaseTwiMaster();
269+
}
270+
271+
// Master-or-Slave Public Methods //////////////////////////////////////////////
272+
273+
void TwoWireMasterOrSlave::begin(int sda, int scl, uint8_t address)
274+
{
275+
twi_setAddress(address);
276+
twi_attachSlaveTxEventWithTarget(onRequestService);
277+
twi_attachSlaveRxEventWithTarget(onReceiveService);
278+
begin(sda, scl);
279+
}
280+
281+
void TwoWireMasterOrSlave::begin(uint8_t address)
282+
{
283+
twi_setAddress(address);
284+
twi_attachSlaveTxEventWithTarget(onRequestService);
285+
twi_attachSlaveRxEventWithTarget(onReceiveService);
286+
begin();
287+
}
288+
void TwoWireMasterOrSlave::begin(int address)
289+
{
290+
begin((uint8_t)address);
291+
}
292+
293+
void TwoWireMasterOrSlave::onReceiveService(uint8_t* inBytes, size_t numBytes, void* targetObject)
294+
{
295+
auto& instance = *(TwoWireMasterOrSlave*)targetObject;
296+
297+
// return if targetObject (an instance of TwoWireMasterOrSlave) was not set/received correctly
298+
// don't bother if user hasn't registered a callback
299+
if (targetObject == nullptr || !instance.user_onReceive)
300+
{
301+
return;
302+
}
303+
// // don't bother if rx buffer is in use by a master requestFrom() op
304+
// // i know this drops data, but it allows for slight stupidity
305+
// // meaning, they may not have read all the master requestFrom() data yet
306+
// if(rxBufferIndex < rxBufferLength){
307+
// return;
308+
// }
309+
310+
// copy twi rx buffer into local read buffer
311+
// this enables new reads to happen in parallel
312+
for (uint8_t i = 0; i < numBytes; ++i)
313+
{
314+
instance.rxBuffer[i] = inBytes[i];
315+
}
316+
317+
// set rx iterator vars
318+
instance.rxBufferIndex = 0;
319+
instance.rxBufferLength = numBytes;
320+
321+
// alert user program
322+
instance.user_onReceive(numBytes);
323+
}
324+
325+
void TwoWireMasterOrSlave::onRequestService(void* targetObject)
326+
{
327+
auto& instance = *(TwoWireMasterOrSlave*)targetObject;
328+
329+
// return if targetObject (an instance of TwoWireMasterOrSlave) was not set/received correctly
330+
// don't bother if user hasn't registered a callback
331+
if (targetObject == nullptr || !instance.user_onRequest)
332+
{
333+
return;
334+
}
335+
336+
// reset tx buffer iterator vars
337+
// !!! this will kill any pending pre-master sendTo() activity
338+
instance.txBufferIndex = 0;
339+
instance.txBufferLength = 0;
340+
341+
// alert user program
342+
instance.user_onRequest();
343+
}
344+
345+
void TwoWireMasterOrSlave::onReceive(void (*function)(int))
346+
{
347+
// arduino api compatibility fixer:
348+
// really hope size parameter will not exceed 2^31 :)
349+
static_assert(sizeof(int) == sizeof(size_t), "something is wrong in Arduino kingdom");
350+
user_onReceive = reinterpret_cast<void(*)(size_t)>(function);
351+
}
352+
353+
void TwoWireMasterOrSlave::onReceive(void (*function)(size_t))
354+
{
355+
user_onReceive = function;
356+
twi_enableSlaveModeWithTarget(this);
357+
}
358+
359+
void TwoWireMasterOrSlave::onRequest(void (*function)(void))
360+
{
361+
user_onRequest = function;
362+
twi_enableSlaveModeWithTarget(this);
363+
}
364+
365+
// Preinstantiate Objects //////////////////////////////////////////////////////
233366
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE)
234-
TwoWire Wire;
367+
static uint8_t _rxBuffer[I2C_BUFFER_LENGTH];
368+
static uint8_t _txBuffer[I2C_BUFFER_LENGTH];
369+
370+
TwoWire Wire{I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH, _rxBuffer, _txBuffer};
371+
372+
TwoWireMasterOrSlave::TwoWireMasterOrSlave()
373+
: TwoWireBase(&twiMasterSingleton, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH, _txBuffer, _rxBuffer)
374+
{}
375+
376+
#else
377+
378+
TwoWireMasterOrSlave::TwoWireMasterOrSlave()
379+
: TwoWireBase(&twiMasterSingleton, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH, new uint8_t[I2C_BUFFER_LENGTH], new uint8_t[I2C_BUFFER_LENGTH])
380+
{}
381+
235382
#endif

0 commit comments

Comments
 (0)