mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 12:51:24 +01:00
Add option to suppress I2C retries.
I2CRB method suppressRetries() added to allow retries to be suppressed.
This commit is contained in:
parent
6e69df2da8
commit
538519dd9d
@ -81,8 +81,13 @@ void I2CManagerClass::forceClock(uint32_t speed) {
|
||||
|
||||
// Check if specified I2C address is responding (blocking operation)
|
||||
// Returns I2C_STATUS_OK (0) if OK, or error code.
|
||||
// Suppress retries. If it doesn't respond first time it's out of the running.
|
||||
uint8_t I2CManagerClass::checkAddress(uint8_t address) {
|
||||
return write(address, NULL, 0);
|
||||
I2CRB rb;
|
||||
rb.setWriteParams(address, NULL, 0);
|
||||
rb.suppressRetries(true);
|
||||
queueRequest(&rb);
|
||||
return rb.wait();
|
||||
}
|
||||
|
||||
|
||||
@ -244,3 +249,9 @@ void I2CRB::setWriteParams(uint8_t i2cAddress, const uint8_t *writeBuffer, uint8
|
||||
this->status = I2C_STATUS_OK;
|
||||
}
|
||||
|
||||
void I2CRB::suppressRetries(bool suppress) {
|
||||
if (suppress)
|
||||
this->operation |= OPERATION_NORETRY;
|
||||
else
|
||||
this->operation &= ~OPERATION_NORETRY;
|
||||
}
|
||||
|
@ -157,6 +157,8 @@ typedef enum : uint8_t
|
||||
OPERATION_REQUEST = 2,
|
||||
OPERATION_SEND = 3,
|
||||
OPERATION_SEND_P = 4,
|
||||
OPERATION_NORETRY = 0x80, // OR with operation to suppress retries.
|
||||
OPERATION_MASK = 0x7f, // mask for extracting the operation code
|
||||
} OperationEnum;
|
||||
|
||||
|
||||
@ -178,6 +180,7 @@ public:
|
||||
void setReadParams(uint8_t i2cAddress, uint8_t *readBuffer, uint8_t readLen);
|
||||
void setRequestParams(uint8_t i2cAddress, uint8_t *readBuffer, uint8_t readLen, const uint8_t *writeBuffer, uint8_t writeLen);
|
||||
void setWriteParams(uint8_t i2cAddress, const uint8_t *writeBuffer, uint8_t writeLen);
|
||||
void suppressRetries(bool suppress);
|
||||
|
||||
uint8_t writeLen;
|
||||
uint8_t readLen;
|
||||
|
@ -105,7 +105,7 @@ void I2CManagerClass::startTransaction() {
|
||||
currentRequest = queueHead;
|
||||
rxCount = txCount = 0;
|
||||
// Copy key fields to static data for speed.
|
||||
operation = currentRequest->operation;
|
||||
operation = currentRequest->operation & OPERATION_MASK;
|
||||
// Start the I2C process going.
|
||||
I2C_sendStart();
|
||||
startTime = micros();
|
||||
@ -227,8 +227,10 @@ void I2CManagerClass::handleInterrupt() {
|
||||
// and state isn't active then state contains the completion status of the request.
|
||||
if (state != I2C_STATE_ACTIVE && currentRequest != NULL) {
|
||||
// Operation has completed.
|
||||
if (state == I2C_STATUS_OK || ++retryCounter > MAX_I2C_RETRIES) {
|
||||
// Status is OK, or has failed and retry count exceeded.
|
||||
if (state == I2C_STATUS_OK || ++retryCounter > MAX_I2C_RETRIES
|
||||
|| currentRequest->operation & OPERATION_NORETRY)
|
||||
{
|
||||
// Status is OK, or has failed and retry count exceeded, or retries disabled.
|
||||
// Remove completed request from head of queue
|
||||
I2CRB * t = queueHead;
|
||||
if (t == currentRequest) {
|
||||
|
@ -51,11 +51,14 @@ void I2CManagerClass::_setClock(unsigned long i2cClockSpeed) {
|
||||
uint8_t I2CManagerClass::write(uint8_t address, const uint8_t buffer[], uint8_t size, I2CRB *rb) {
|
||||
uint8_t status = I2C_STATUS_OK;
|
||||
uint8_t retryCount = 0;
|
||||
// If request fails, retry up to the defined limit, unless the NORETRY flag is set
|
||||
// in the request block.
|
||||
do {
|
||||
Wire.beginTransmission(address);
|
||||
if (size > 0) Wire.write(buffer, size);
|
||||
status = Wire.endTransmission();
|
||||
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES));
|
||||
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES
|
||||
|| rb->operation & OPERATION_NORETRY));
|
||||
rb->status = status;
|
||||
return I2C_STATUS_OK;
|
||||
}
|
||||
@ -81,6 +84,8 @@ uint8_t I2CManagerClass::read(uint8_t address, uint8_t readBuffer[], uint8_t rea
|
||||
uint8_t status = I2C_STATUS_OK;
|
||||
uint8_t nBytes = 0;
|
||||
uint8_t retryCount = 0;
|
||||
// If request fails, retry up to the defined limit, unless the NORETRY flag is set
|
||||
// in the request block.
|
||||
do {
|
||||
if (writeSize > 0) {
|
||||
Wire.beginTransmission(address);
|
||||
@ -93,7 +98,8 @@ uint8_t I2CManagerClass::read(uint8_t address, uint8_t readBuffer[], uint8_t rea
|
||||
readBuffer[nBytes++] = Wire.read();
|
||||
if (nBytes < readSize) status = I2C_STATUS_TRUNCATED;
|
||||
}
|
||||
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES));
|
||||
} while (!(status == I2C_STATUS_OK || ++retryCount > MAX_I2C_RETRIES
|
||||
|| rb->operation & OPERATION_NORETRY));
|
||||
|
||||
rb->nBytes = nBytes;
|
||||
rb->status = status;
|
||||
@ -109,7 +115,7 @@ uint8_t I2CManagerClass::read(uint8_t address, uint8_t readBuffer[], uint8_t rea
|
||||
* the non-blocking version.
|
||||
***************************************************************************/
|
||||
void I2CManagerClass::queueRequest(I2CRB *req) {
|
||||
switch (req->operation) {
|
||||
switch (req->operation & OPERATION_MASK) {
|
||||
case OPERATION_READ:
|
||||
read(req->i2cAddress, req->readBuffer, req->readLen, NULL, 0, req);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user