mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-22 23:56:13 +01:00
I2CManager: Refactor common driver code.
Put mux handling into I2CManager_NonBlocking.h to keep the native (controller-specific) drivers more simple. Remove almost all but one of the static definitions, in preparation for supporting multiple I2C buses.
This commit is contained in:
parent
18b148ed1f
commit
553a94bf67
|
@ -72,6 +72,10 @@ void I2CManagerClass::begin(void) {
|
||||||
_beginCompleted = true;
|
_beginCompleted = true;
|
||||||
_initialise();
|
_initialise();
|
||||||
|
|
||||||
|
#if defined(I2C_USE_WIRE)
|
||||||
|
DIAG(F("I2CManager: Using Wire library"));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check for short-circuits on I2C
|
// Check for short-circuits on I2C
|
||||||
if (!digitalRead(SDA))
|
if (!digitalRead(SDA))
|
||||||
DIAG(F("WARNING: Possible short-circuit on I2C SDA line"));
|
DIAG(F("WARNING: Possible short-circuit on I2C SDA line"));
|
||||||
|
@ -81,7 +85,7 @@ void I2CManagerClass::begin(void) {
|
||||||
// Probe and list devices. Use standard mode
|
// Probe and list devices. Use standard mode
|
||||||
// (clock speed 100kHz) for best device compatibility.
|
// (clock speed 100kHz) for best device compatibility.
|
||||||
_setClock(100000);
|
_setClock(100000);
|
||||||
unsigned long originalTimeout = timeout;
|
unsigned long originalTimeout = _timeout;
|
||||||
setTimeout(1000); // use 1ms timeout for probes
|
setTimeout(1000); // use 1ms timeout for probes
|
||||||
|
|
||||||
#if defined(I2C_EXTENDED_ADDRESS)
|
#if defined(I2C_EXTENDED_ADDRESS)
|
||||||
|
@ -110,7 +114,7 @@ void I2CManagerClass::begin(void) {
|
||||||
uint8_t muxAddr = I2C_MUX_BASE_ADDRESS + muxNo;
|
uint8_t muxAddr = I2C_MUX_BASE_ADDRESS + muxNo;
|
||||||
if (exists(muxAddr)) {
|
if (exists(muxAddr)) {
|
||||||
// Select Mux Subbus
|
// Select Mux Subbus
|
||||||
for (uint8_t subBus=0; subBus<=7; subBus++) {
|
for (uint8_t subBus=0; subBus<=SubBus_No; subBus++) {
|
||||||
muxSelectSubBus({(I2CMux)muxNo, (I2CSubBus)subBus});
|
muxSelectSubBus({(I2CMux)muxNo, (I2CSubBus)subBus});
|
||||||
for (uint8_t addr=0x08; addr<0x78; addr++) {
|
for (uint8_t addr=0x08; addr<0x78; addr++) {
|
||||||
if (exists(addr)) {
|
if (exists(addr)) {
|
||||||
|
@ -261,26 +265,9 @@ const FSH *I2CManagerClass::getErrorMessage(uint8_t status) {
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
I2CManagerClass I2CManager = I2CManagerClass();
|
I2CManagerClass I2CManager = I2CManagerClass();
|
||||||
|
|
||||||
// Default timeout 100ms on I2C request block completion.
|
|
||||||
// A full 32-byte transmission takes about 8ms at 100kHz,
|
|
||||||
// so this value allows lots of headroom.
|
|
||||||
// It can be modified by calling I2CManager.setTimeout() function.
|
|
||||||
// When retries are enabled, the timeout applies to each
|
|
||||||
// try, and failure from timeout does not get retried.
|
|
||||||
unsigned long I2CManagerClass::timeout = 100000UL;
|
|
||||||
|
|
||||||
// Buffer for conversion of I2CAddress to char*.
|
// Buffer for conversion of I2CAddress to char*.
|
||||||
/* static */ char I2CAddress::addressBuffer[30];
|
/* static */ char I2CAddress::addressBuffer[30];
|
||||||
|
|
||||||
#if defined(I2C_EXTENDED_ADDRESS)
|
|
||||||
// Count of I2C multiplexers found when initialising. If there is only one
|
|
||||||
// MUX then the subbus does not de-selecting after use; however, if there
|
|
||||||
// is two or more, then the subbus must be deselected to avoid multiple
|
|
||||||
// sub-bus legs on different multiplexers being accessible simultaneously.
|
|
||||||
uint8_t I2CManagerClass::_muxCount = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Helper functions associated with I2C Request Block
|
// Helper functions associated with I2C Request Block
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -346,3 +333,16 @@ void I2CRB::suppressRetries(bool suppress) {
|
||||||
else
|
else
|
||||||
this->operation &= ~OPERATION_NORETRY;
|
this->operation &= ~OPERATION_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for converting a uint8_t to four characters (e.g. 0x23).
|
||||||
|
void I2CAddress::toHex(const uint8_t value, char *buffer) {
|
||||||
|
char *ptr = buffer;
|
||||||
|
// Just display hex value, two digits.
|
||||||
|
*ptr++ = '0';
|
||||||
|
*ptr++ = 'x';
|
||||||
|
uint8_t bits = (value >> 4) & 0xf;
|
||||||
|
*ptr++ = bits > 9 ? bits-10+'a' : bits+'0';
|
||||||
|
bits = value & 0xf;
|
||||||
|
*ptr++ = bits > 9 ? bits-10+'a' : bits+'0';
|
||||||
|
}
|
129
I2CManager.h
129
I2CManager.h
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "FSH.h"
|
#include "FSH.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Manager for I2C communications. For portability, it allows use
|
* Manager for I2C communications. For portability, it allows use
|
||||||
|
@ -104,7 +105,7 @@
|
||||||
*
|
*
|
||||||
* Non-interrupting I2C:
|
* Non-interrupting I2C:
|
||||||
*
|
*
|
||||||
* I2C may be operated without interrupts (undefine I2C_USE_INTERRUPTS). Instead, the I2C state
|
* Non-blocking I2C may be operated without interrupts (undefine I2C_USE_INTERRUPTS). Instead, the I2C state
|
||||||
* machine handler, currently invoked from the interrupt service routine, is invoked from the loop() function.
|
* machine handler, currently invoked from the interrupt service routine, is invoked from the loop() function.
|
||||||
* The speed at which I2C operations can be performed then becomes highly dependent on the frequency that
|
* The speed at which I2C operations can be performed then becomes highly dependent on the frequency that
|
||||||
* the loop() function is called, and may be adequate under some circumstances.
|
* the loop() function is called, and may be adequate under some circumstances.
|
||||||
|
@ -151,6 +152,11 @@
|
||||||
// I2C multiplexer support.
|
// I2C multiplexer support.
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Currently only one bus supported, and one instance of I2CManager to handle it.
|
||||||
|
enum I2CBus : uint8_t {
|
||||||
|
I2CBus_0 = 0,
|
||||||
|
};
|
||||||
|
|
||||||
// Currently I2CAddress supports one I2C bus, with up to eight
|
// Currently I2CAddress supports one I2C bus, with up to eight
|
||||||
// multipexers (MUX) attached. Each MUX can have up to eight sub-buses.
|
// multipexers (MUX) attached. Each MUX can have up to eight sub-buses.
|
||||||
enum I2CMux : uint8_t {
|
enum I2CMux : uint8_t {
|
||||||
|
@ -168,12 +174,17 @@ enum I2CMux : uint8_t {
|
||||||
enum I2CSubBus : uint8_t {
|
enum I2CSubBus : uint8_t {
|
||||||
SubBus_0 = 0, // Enable individual sub-buses...
|
SubBus_0 = 0, // Enable individual sub-buses...
|
||||||
SubBus_1 = 1,
|
SubBus_1 = 1,
|
||||||
|
#if !defined(I2CMUX_PCA9542)
|
||||||
SubBus_2 = 2,
|
SubBus_2 = 2,
|
||||||
SubBus_3 = 3,
|
SubBus_3 = 3,
|
||||||
|
#if !defined(I2CMUX_PCA9544)
|
||||||
SubBus_4 = 4,
|
SubBus_4 = 4,
|
||||||
SubBus_5 = 5,
|
SubBus_5 = 5,
|
||||||
SubBus_6 = 6,
|
SubBus_6 = 6,
|
||||||
SubBus_7 = 7,
|
SubBus_7 = 7,
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
SubBus_No, // Number of subbuses (highest + 1)
|
||||||
SubBus_None = 254, // Disable all sub-buses on selected mux
|
SubBus_None = 254, // Disable all sub-buses on selected mux
|
||||||
SubBus_All = 255, // Enable all sub-buses
|
SubBus_All = 255, // Enable all sub-buses
|
||||||
};
|
};
|
||||||
|
@ -189,14 +200,16 @@ enum I2CSubBus : uint8_t {
|
||||||
struct I2CAddress {
|
struct I2CAddress {
|
||||||
private:
|
private:
|
||||||
// Fields
|
// Fields
|
||||||
|
I2CBus _busNumber;
|
||||||
I2CMux _muxNumber;
|
I2CMux _muxNumber;
|
||||||
I2CSubBus _subBus;
|
I2CSubBus _subBus;
|
||||||
uint8_t _deviceAddress;
|
uint8_t _deviceAddress;
|
||||||
static char addressBuffer[];
|
static char addressBuffer[];
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
// For I2CAddress "{Mux_0, SubBus_0, 0x23}" syntax.
|
// For I2CAddress "{I2CBus_0, Mux_0, SubBus_0, 0x23}" syntax.
|
||||||
I2CAddress(const I2CMux muxNumber, const I2CSubBus subBus, const uint8_t deviceAddress) {
|
I2CAddress(const I2CBus busNumber, const I2CMux muxNumber, const I2CSubBus subBus, const uint8_t deviceAddress) {
|
||||||
|
_busNumber = busNumber;
|
||||||
_muxNumber = muxNumber;
|
_muxNumber = muxNumber;
|
||||||
_subBus = subBus;
|
_subBus = subBus;
|
||||||
_deviceAddress = deviceAddress;
|
_deviceAddress = deviceAddress;
|
||||||
|
@ -205,6 +218,10 @@ public:
|
||||||
// Basic constructor
|
// Basic constructor
|
||||||
I2CAddress() : I2CAddress(I2CMux_None, SubBus_None, 0) {}
|
I2CAddress() : I2CAddress(I2CMux_None, SubBus_None, 0) {}
|
||||||
|
|
||||||
|
// For I2CAddress "{Mux_0, SubBus_0, 0x23}" syntax.
|
||||||
|
I2CAddress(const I2CMux muxNumber, const I2CSubBus subBus, const uint8_t deviceAddress) :
|
||||||
|
I2CAddress(I2CBus_0, muxNumber, subBus, deviceAddress) {}
|
||||||
|
|
||||||
// For I2CAddress in form "{SubBus_0, 0x23}" - assume Mux0 (0x70)
|
// For I2CAddress in form "{SubBus_0, 0x23}" - assume Mux0 (0x70)
|
||||||
I2CAddress(I2CSubBus subBus, uint8_t deviceAddress) :
|
I2CAddress(I2CSubBus subBus, uint8_t deviceAddress) :
|
||||||
I2CAddress(I2CMux_0, subBus, deviceAddress) {}
|
I2CAddress(I2CMux_0, subBus, deviceAddress) {}
|
||||||
|
@ -214,6 +231,12 @@ public:
|
||||||
// (device assumed to be on the main I2C bus).
|
// (device assumed to be on the main I2C bus).
|
||||||
I2CAddress(const uint8_t deviceAddress) :
|
I2CAddress(const uint8_t deviceAddress) :
|
||||||
I2CAddress(I2CMux_None, SubBus_None, deviceAddress) {}
|
I2CAddress(I2CMux_None, SubBus_None, deviceAddress) {}
|
||||||
|
|
||||||
|
// Conversion from uint8_t to I2CAddress
|
||||||
|
// For I2CAddress in form "{I2CBus_1, 0x23}"
|
||||||
|
// (device not connected via multiplexer).
|
||||||
|
I2CAddress(const I2CBus bus, const uint8_t deviceAddress) :
|
||||||
|
I2CAddress(bus, I2CMux_None, SubBus_None, deviceAddress) {}
|
||||||
|
|
||||||
// For I2CAddress in form "{I2CMux_0, SubBus_0}" (mux selector)
|
// For I2CAddress in form "{I2CMux_0, SubBus_0}" (mux selector)
|
||||||
I2CAddress(const I2CMux muxNumber, const I2CSubBus subBus) :
|
I2CAddress(const I2CMux muxNumber, const I2CSubBus subBus) :
|
||||||
|
@ -250,14 +273,8 @@ public:
|
||||||
*ptr++ = '0' + _subBus;
|
*ptr++ = '0' + _subBus;
|
||||||
*ptr++ = ',';
|
*ptr++ = ',';
|
||||||
}
|
}
|
||||||
uint8_t temp = _deviceAddress;
|
toHex(_deviceAddress, ptr);
|
||||||
*ptr++ = '0';
|
ptr += 4;
|
||||||
*ptr++ = 'x';
|
|
||||||
for (uint8_t index = 0; index<2; index++) {
|
|
||||||
uint8_t bits = (temp >> 4) & 0x0f;
|
|
||||||
*ptr++ = bits > 9 ? bits-10+'A' : bits+'0';
|
|
||||||
temp <<= 4;
|
|
||||||
}
|
|
||||||
if (_muxNumber != I2CMux_None)
|
if (_muxNumber != I2CMux_None)
|
||||||
*ptr++ = '}';
|
*ptr++ = '}';
|
||||||
*ptr = 0; // terminate string
|
*ptr = 0; // terminate string
|
||||||
|
@ -282,6 +299,10 @@ public:
|
||||||
I2CMux muxNumber() { return _muxNumber; }
|
I2CMux muxNumber() { return _muxNumber; }
|
||||||
I2CSubBus subBus() { return _subBus; }
|
I2CSubBus subBus() { return _subBus; }
|
||||||
uint8_t deviceAddress() { return _deviceAddress; }
|
uint8_t deviceAddress() { return _deviceAddress; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Helper function for converting byte to four-character hex string (e.g. 0x23).
|
||||||
|
void toHex(const uint8_t value, char *buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -308,14 +329,8 @@ public:
|
||||||
const char* toString () {
|
const char* toString () {
|
||||||
char *ptr = addressBuffer;
|
char *ptr = addressBuffer;
|
||||||
// Just display hex value, two digits.
|
// Just display hex value, two digits.
|
||||||
uint8_t temp = _deviceAddress;
|
toHex(_deviceAddress, ptr);
|
||||||
*ptr++ = '0';
|
ptr += 4;
|
||||||
*ptr++ = 'x';
|
|
||||||
for (uint8_t index = 0; index<2; index++) {
|
|
||||||
uint8_t bits = (temp >> 4) & 0xf;
|
|
||||||
*ptr++ = bits > 9 ? bits-10+'a' : bits+'0';
|
|
||||||
temp <<= 4;
|
|
||||||
}
|
|
||||||
*ptr = 0; // terminate string
|
*ptr = 0; // terminate string
|
||||||
return addressBuffer;
|
return addressBuffer;
|
||||||
}
|
}
|
||||||
|
@ -326,9 +341,10 @@ public:
|
||||||
return false; // Different device address so no match
|
return false; // Different device address so no match
|
||||||
return true; // Same address on same mux and same subbus
|
return true; // Same address on same mux and same subbus
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
// Helper function for converting byte to four-character hex string (e.g. 0x23).
|
||||||
|
void toHex(const uint8_t value, char *buffer);
|
||||||
};
|
};
|
||||||
// Legacy single-byte I2C address type for compact code and smooth changeover.
|
|
||||||
//typedef uint8_t I2CAddress;
|
|
||||||
#endif // I2C_EXTENDED_ADDRESS
|
#endif // I2C_EXTENDED_ADDRESS
|
||||||
|
|
||||||
|
|
||||||
|
@ -452,12 +468,19 @@ public:
|
||||||
private:
|
private:
|
||||||
bool _beginCompleted = false;
|
bool _beginCompleted = false;
|
||||||
bool _clockSpeedFixed = false;
|
bool _clockSpeedFixed = false;
|
||||||
static uint8_t retryCounter; // Count of retries
|
uint8_t retryCounter; // Count of retries
|
||||||
// Clock speed must be no higher than 400kHz on AVR. Higher is possible on 4809, SAMD
|
// Clock speed must be no higher than 400kHz on AVR. Higher is possible on 4809, SAMD
|
||||||
// and STM32 but most popular I2C devices are 400kHz so in practice the higher speeds
|
// and STM32 but most popular I2C devices are 400kHz so in practice the higher speeds
|
||||||
// will not be useful. The speed can be overridden by I2CManager::forceClock().
|
// will not be useful. The speed can be overridden by I2CManager::forceClock().
|
||||||
uint32_t _clockSpeed = I2C_FREQ;
|
uint32_t _clockSpeed = I2C_FREQ;
|
||||||
static unsigned long timeout; // Transaction timeout in microseconds. 0=disabled.
|
// Default timeout 100ms on I2C request block completion.
|
||||||
|
// A full 32-byte transmission takes about 8ms at 100kHz,
|
||||||
|
// so this value allows lots of headroom.
|
||||||
|
// It can be modified by calling I2CManager.setTimeout() function.
|
||||||
|
// When retries are enabled, the timeout applies to each
|
||||||
|
// try, and failure from timeout does not get retried.
|
||||||
|
// A value of 0 means disable timeout monitoring.
|
||||||
|
unsigned long _timeout = 100000UL;
|
||||||
|
|
||||||
// Finish off request block by waiting for completion and posting status.
|
// Finish off request block by waiting for completion and posting status.
|
||||||
uint8_t finishRB(I2CRB *rb, uint8_t status);
|
uint8_t finishRB(I2CRB *rb, uint8_t status);
|
||||||
|
@ -466,7 +489,11 @@ private:
|
||||||
void _setClock(unsigned long);
|
void _setClock(unsigned long);
|
||||||
|
|
||||||
#if defined(I2C_EXTENDED_ADDRESS)
|
#if defined(I2C_EXTENDED_ADDRESS)
|
||||||
static uint8_t _muxCount;
|
// Count of I2C multiplexers found when initialising. If there is only one
|
||||||
|
// MUX then the subbus does not de-selecting after use; however, if there
|
||||||
|
// are two or more, then the subbus must be deselected to avoid multiple
|
||||||
|
// sub-bus legs on different multiplexers being accessible simultaneously.
|
||||||
|
uint8_t _muxCount = 0;
|
||||||
uint8_t getMuxCount() { return _muxCount; }
|
uint8_t getMuxCount() { return _muxCount; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -479,40 +506,56 @@ private:
|
||||||
// Within the queue, each request's nextRequest field points to the
|
// Within the queue, each request's nextRequest field points to the
|
||||||
// next request, or NULL.
|
// next request, or NULL.
|
||||||
// Mark volatile as they are updated by IRC and read/written elsewhere.
|
// Mark volatile as they are updated by IRC and read/written elsewhere.
|
||||||
static I2CRB * volatile queueHead;
|
I2CRB * volatile queueHead = NULL;
|
||||||
static I2CRB * volatile queueTail;
|
I2CRB * volatile queueTail = NULL;
|
||||||
static volatile uint8_t state;
|
|
||||||
static uint8_t completionStatus;
|
|
||||||
|
|
||||||
static I2CRB * volatile currentRequest;
|
// State is set to I2C_STATE_FREE when the interrupt handler has finished
|
||||||
static volatile uint8_t txCount;
|
// the current request and is ready to complete.
|
||||||
static volatile uint8_t rxCount;
|
uint8_t state = I2C_STATE_FREE;
|
||||||
static volatile uint8_t bytesToSend;
|
|
||||||
static volatile uint8_t bytesToReceive;
|
// CompletionStatus may be set by the interrupt handler at any time but is
|
||||||
static volatile uint8_t operation;
|
// not written to the I2CRB until the state is I2C_STATE_FREE.
|
||||||
static volatile unsigned long startTime;
|
uint8_t completionStatus = I2C_STATUS_OK;
|
||||||
static volatile uint8_t muxPhase;
|
uint8_t overallStatus = I2C_STATUS_OK;
|
||||||
|
|
||||||
|
I2CRB * currentRequest = NULL;
|
||||||
|
uint8_t txCount = 0;
|
||||||
|
uint8_t rxCount = 0;
|
||||||
|
uint8_t bytesToSend = 0;
|
||||||
|
uint8_t bytesToReceive = 0;
|
||||||
|
uint8_t operation = 0;
|
||||||
|
unsigned long startTime = 0;
|
||||||
|
uint8_t muxPhase = 0;
|
||||||
|
uint8_t muxAddress = 0;
|
||||||
|
uint8_t muxData[1];
|
||||||
|
uint8_t deviceAddress;
|
||||||
|
const uint8_t *sendBuffer;
|
||||||
|
uint8_t *receiveBuffer;
|
||||||
|
|
||||||
volatile uint32_t pendingClockSpeed = 0;
|
volatile uint32_t pendingClockSpeed = 0;
|
||||||
|
|
||||||
void startTransaction();
|
void startTransaction();
|
||||||
|
|
||||||
// Low-level hardware manipulation functions.
|
// Low-level hardware manipulation functions.
|
||||||
static void I2C_init();
|
void I2C_init();
|
||||||
static void I2C_setClock(unsigned long i2cClockSpeed);
|
void I2C_setClock(unsigned long i2cClockSpeed);
|
||||||
static void I2C_handleInterrupt();
|
void I2C_handleInterrupt();
|
||||||
static void I2C_sendStart();
|
void I2C_sendStart();
|
||||||
static void I2C_sendStop();
|
void I2C_sendStop();
|
||||||
static void I2C_close();
|
void I2C_close();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// handleInterrupt needs to be public to be called from the ISR function!
|
// handleInterrupt needs to be public to be called from the ISR function!
|
||||||
static void handleInterrupt();
|
void handleInterrupt();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Pointer to class instance (Note: if there is more than one bus, each will have
|
||||||
|
// its own instance of I2CManager, selected by the queueRequest function from
|
||||||
|
// the I2CBus field within the request block's I2CAddress).
|
||||||
extern I2CManagerClass I2CManager;
|
extern I2CManagerClass I2CManager;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
void I2CManagerClass::_initialise() {
|
void I2CManagerClass::_initialise() {
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
#if defined(WIRE_HAS_TIMEOUT)
|
#if defined(WIRE_HAS_TIMEOUT)
|
||||||
Wire.setWireTimeout(timeout, true);
|
Wire.setWireTimeout(_timeout, true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ void I2CManagerClass::_setClock(unsigned long i2cClockSpeed) {
|
||||||
* read is started.
|
* read is started.
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
void I2CManagerClass::setTimeout(unsigned long value) {
|
void I2CManagerClass::setTimeout(unsigned long value) {
|
||||||
timeout = value;
|
_timeout = value;
|
||||||
#if defined(WIRE_HAS_TIMEOUT)
|
#if defined(WIRE_HAS_TIMEOUT)
|
||||||
Wire.setWireTimeout(value, true);
|
Wire.setWireTimeout(value, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user