mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 08:06:13 +01:00
Fix read operations on I2CManager for SAMD
This commit is contained in:
parent
d0ce59b19f
commit
291a331f3e
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* © 2022 Paul M Antoine
|
* © 2022 Paul M Antoine
|
||||||
* © 2021, Neil McKechnie
|
* © 2023, Neil McKechnie
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -107,8 +107,8 @@ void I2CManagerClass::I2C_init()
|
||||||
s->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )/* |
|
s->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )/* |
|
||||||
SERCOM_I2CM_CTRLA_SCLSM*/ ;
|
SERCOM_I2CM_CTRLA_SCLSM*/ ;
|
||||||
|
|
||||||
// Enable Smart mode and Quick Command
|
// Enable Smart mode (but not Quick Command)
|
||||||
s->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN | SERCOM_I2CM_CTRLB_QCEN;
|
s->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
|
||||||
|
|
||||||
#if defined(I2C_USE_INTERRUPTS)
|
#if defined(I2C_USE_INTERRUPTS)
|
||||||
// Setting NVIC
|
// Setting NVIC
|
||||||
|
@ -141,7 +141,7 @@ void I2CManagerClass::I2C_init()
|
||||||
PORT->Group[g_APinDescription[PIN_WIRE_SCL].ulPort].PINCFG[g_APinDescription[PIN_WIRE_SCL].ulPin].reg =
|
PORT->Group[g_APinDescription[PIN_WIRE_SCL].ulPort].PINCFG[g_APinDescription[PIN_WIRE_SCL].ulPin].reg =
|
||||||
PORT_PINCFG_DRVSTR | PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
|
PORT_PINCFG_DRVSTR | PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
|
||||||
PORT->Group[g_APinDescription[PIN_WIRE_SDA].ulPort].PINCFG[g_APinDescription[PIN_WIRE_SDA].ulPin].reg =
|
PORT->Group[g_APinDescription[PIN_WIRE_SDA].ulPort].PINCFG[g_APinDescription[PIN_WIRE_SDA].ulPin].reg =
|
||||||
PORT_PINCFG_DRVSTR | PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
|
PORT_PINCFG_DRVSTR | PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -152,18 +152,21 @@ void I2CManagerClass::I2C_sendStart() {
|
||||||
bytesToReceive = currentRequest->readLen;
|
bytesToReceive = currentRequest->readLen;
|
||||||
|
|
||||||
// We may have initiated a stop bit before this without waiting for it.
|
// We may have initiated a stop bit before this without waiting for it.
|
||||||
// Wait for stop bit to be sent before sending start.
|
// However, the state machine ensures that the start bit isn't sent
|
||||||
while (s->I2CM.STATUS.bit.BUSSTATE == 0x2);
|
// until the stop bit is complete.
|
||||||
|
//while (s->I2CM.STATUS.bit.BUSSTATE == 0x2);
|
||||||
|
|
||||||
// If anything to send, initiate write. Otherwise initiate read.
|
// If anything to send, initiate write. Otherwise initiate read.
|
||||||
if (operation == OPERATION_READ || ((operation == OPERATION_REQUEST) && !bytesToSend))
|
if (operation == OPERATION_READ || ((operation == OPERATION_REQUEST) && !bytesToSend))
|
||||||
{
|
{
|
||||||
|
// Wait while the I2C bus is BUSY
|
||||||
|
//while (s->I2CM.STATUS.bit.BUSSTATE != 0x1);
|
||||||
// Send start and address with read/write flag or'd in
|
// Send start and address with read/write flag or'd in
|
||||||
s->I2CM.ADDR.bit.ADDR = (currentRequest->i2cAddress << 1) | 1;
|
s->I2CM.ADDR.bit.ADDR = (currentRequest->i2cAddress << 1) | 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Wait while the I2C bus is BUSY
|
// Wait while the I2C bus is BUSY
|
||||||
while (s->I2CM.STATUS.bit.BUSSTATE != 0x1);
|
//while (s->I2CM.STATUS.bit.BUSSTATE != 0x1);
|
||||||
s->I2CM.ADDR.bit.ADDR = (currentRequest->i2cAddress << 1ul) | 0;
|
s->I2CM.ADDR.bit.ADDR = (currentRequest->i2cAddress << 1ul) | 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,14 +206,11 @@ void I2CManagerClass::I2C_handleInterrupt() {
|
||||||
state = I2C_STATUS_NEGATIVE_ACKNOWLEDGE;
|
state = I2C_STATUS_NEGATIVE_ACKNOWLEDGE;
|
||||||
} else if (bytesToSend) {
|
} else if (bytesToSend) {
|
||||||
// Acked, so send next byte
|
// Acked, so send next byte
|
||||||
if (currentRequest->operation == OPERATION_SEND_P)
|
s->I2CM.DATA.bit.DATA = currentRequest->writeBuffer[txCount++];
|
||||||
s->I2CM.DATA.bit.DATA = GETFLASH(currentRequest->writeBuffer + (txCount++));
|
|
||||||
else
|
|
||||||
s->I2CM.DATA.bit.DATA = currentRequest->writeBuffer[txCount++];
|
|
||||||
bytesToSend--;
|
bytesToSend--;
|
||||||
} else if (bytesToReceive) {
|
} else if (bytesToReceive) {
|
||||||
// Last sent byte acked and no more to send. Send repeated start, address and read bit.
|
// Last sent byte acked and no more to send. Send repeated start, address and read bit.
|
||||||
s->I2CM.ADDR.bit.ADDR = (currentRequest->i2cAddress << 1) | 1;
|
s->I2CM.ADDR.bit.ADDR = (currentRequest->i2cAddress << 1) | 1;
|
||||||
} else {
|
} else {
|
||||||
// No more data to send/receive. Initiate a STOP condition.
|
// No more data to send/receive. Initiate a STOP condition.
|
||||||
I2C_sendStop();
|
I2C_sendStop();
|
||||||
|
@ -218,25 +218,16 @@ void I2CManagerClass::I2C_handleInterrupt() {
|
||||||
}
|
}
|
||||||
} else if (s->I2CM.INTFLAG.bit.SB) {
|
} else if (s->I2CM.INTFLAG.bit.SB) {
|
||||||
// Master read completed without errors
|
// Master read completed without errors
|
||||||
if (bytesToReceive) {
|
if (bytesToReceive == 1) {
|
||||||
|
s->I2CM.CTRLB.bit.ACKACT = 1; // NAK final byte
|
||||||
|
I2C_sendStop(); // send stop
|
||||||
|
currentRequest->readBuffer[rxCount++] = s->I2CM.DATA.bit.DATA; // Store received byte
|
||||||
|
bytesToReceive = 0;
|
||||||
|
state = I2C_STATUS_OK; // done
|
||||||
|
} else if (bytesToReceive) {
|
||||||
|
s->I2CM.CTRLB.bit.ACKACT = 0; // ACK all but final byte
|
||||||
currentRequest->readBuffer[rxCount++] = s->I2CM.DATA.bit.DATA; // Store received byte
|
currentRequest->readBuffer[rxCount++] = s->I2CM.DATA.bit.DATA; // Store received byte
|
||||||
bytesToReceive--;
|
bytesToReceive--;
|
||||||
} else {
|
|
||||||
// Buffer full, issue nack/stop
|
|
||||||
s->I2CM.CTRLB.bit.ACKACT = 1;
|
|
||||||
I2C_sendStop();
|
|
||||||
state = I2C_STATUS_OK;
|
|
||||||
}
|
|
||||||
if (bytesToReceive) {
|
|
||||||
// PMA - I think Smart Mode means we have nothing to do...
|
|
||||||
// More bytes to receive, issue ack and start another read
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Transaction finished, issue NACK and STOP.
|
|
||||||
s->I2CM.CTRLB.bit.ACKACT = 1;
|
|
||||||
I2C_sendStop();
|
|
||||||
state = I2C_STATUS_OK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user