|
|
|
|
|
|
|
|
// wait while bus is busy |
|
|
// wait while bus is busy |
|
|
while (1) { |
|
|
while (1) { |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
if (!(LPI2C1_MSR & LPI2C_MSR_BBF)) break; // bus is available |
|
|
|
|
|
if (LPI2C1_MSR & LPI2C_MSR_MBF) break; // we already have bus control |
|
|
|
|
|
|
|
|
if (!(status & LPI2C_MSR_BBF)) break; // bus is available |
|
|
|
|
|
if (status & LPI2C_MSR_MBF) break; // we already have bus control |
|
|
// TODO: timeout... |
|
|
// TODO: timeout... |
|
|
} |
|
|
} |
|
|
printf("idle\n"); |
|
|
|
|
|
|
|
|
//printf("m=%x\n", status); |
|
|
|
|
|
|
|
|
// TODO: is this correct if the prior use didn't send stop? |
|
|
// TODO: is this correct if the prior use didn't send stop? |
|
|
LPI2C1_MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF; // clear flags |
|
|
|
|
|
|
|
|
//LPI2C1_MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF; // clear flags |
|
|
|
|
|
LPI2C1_MSR = status; |
|
|
|
|
|
|
|
|
printf("MSR=%lX, MFSR=%lX\n", status, LPI2C1_MFSR); |
|
|
|
|
|
|
|
|
//printf("MSR=%lX, MFSR=%lX\n", status, LPI2C1_MFSR); |
|
|
|
|
|
//elapsedMillis timeout=0; |
|
|
|
|
|
|
|
|
while (1) { |
|
|
while (1) { |
|
|
// transmit stuff, if we haven't already |
|
|
// transmit stuff, if we haven't already |
|
|
if (i <= len) { |
|
|
if (i <= len) { |
|
|
uint32_t fifo_used = LPI2C1_MFSR & 0x07; // pg 2914 |
|
|
uint32_t fifo_used = LPI2C1_MFSR & 0x07; // pg 2914 |
|
|
if (fifo_used < 4) printf("t=%ld\n", fifo_used); |
|
|
|
|
|
|
|
|
//if (fifo_used < 4) printf("t=%ld\n", fifo_used); |
|
|
while (fifo_used < 4) { |
|
|
while (fifo_used < 4) { |
|
|
if (i == 0) { |
|
|
if (i == 0) { |
|
|
LPI2C1_MTDR = LPI2C_MTDR_CMD_START | (txBuffer[0] << 1); |
|
|
|
|
|
|
|
|
//printf("start %x\n", txBuffer[0]); |
|
|
|
|
|
LPI2C1_MTDR = LPI2C_MTDR_CMD_START | txBuffer[0]; |
|
|
i = 1; |
|
|
i = 1; |
|
|
} else if (i < len) { |
|
|
} else if (i < len) { |
|
|
LPI2C1_MTDR = LPI2C_MTDR_CMD_TRANSMIT | txBuffer[i++]; |
|
|
LPI2C1_MTDR = LPI2C_MTDR_CMD_TRANSMIT | txBuffer[i++]; |
|
|
|
|
|
|
|
|
// monitor status |
|
|
// monitor status |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
if (status & LPI2C_MSR_ALF) { |
|
|
if (status & LPI2C_MSR_ALF) { |
|
|
printf("arbitration lost\n"); |
|
|
|
|
|
|
|
|
//printf("arbitration lost\n"); |
|
|
return 4; // we lost bus arbitration to another master |
|
|
return 4; // we lost bus arbitration to another master |
|
|
} |
|
|
} |
|
|
if (status & LPI2C_MSR_NDF) { |
|
|
if (status & LPI2C_MSR_NDF) { |
|
|
printf("got NACK, fifo=%ld, i=%ld\n", LPI2C1_MFSR & 0x07, i); |
|
|
|
|
|
|
|
|
//printf("NACK, f=%d, i=%d\n", LPI2C1_MFSR & 0x07, i); |
|
|
// TODO: check that hardware really sends stop automatically |
|
|
// TODO: check that hardware really sends stop automatically |
|
|
// TODO: do we need to clear the FIFO here? |
|
|
|
|
|
|
|
|
LPI2C1_MCR = LPI2C_MCR_MEN | LPI2C_MCR_RTF; // clear the FIFO |
|
|
return 2; // NACK for address |
|
|
return 2; // NACK for address |
|
|
//return 3; // NACK for data TODO: how to discern addr from data? |
|
|
//return 3; // NACK for data TODO: how to discern addr from data? |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//printf("bus stuck - what to do?\n"); |
|
|
//printf("bus stuck - what to do?\n"); |
|
|
//return 4; |
|
|
//return 4; |
|
|
//} |
|
|
//} |
|
|
|
|
|
|
|
|
|
|
|
//if (timeout > 100) { |
|
|
|
|
|
//printf("status = %x\n", status); |
|
|
|
|
|
//timeout = 0; |
|
|
|
|
|
//} |
|
|
|
|
|
|
|
|
if (sendStop) { |
|
|
if (sendStop) { |
|
|
if (status & LPI2C_MSR_SDF) return 0; |
|
|
|
|
|
|
|
|
if (status & LPI2C_MSR_SDF) { |
|
|
|
|
|
//printf("stop sent, msr=%x\n", status); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
uint32_t fifo_used = LPI2C1_MFSR & 0x07; // pg 2914 |
|
|
uint32_t fifo_used = LPI2C1_MFSR & 0x07; // pg 2914 |
|
|
if (fifo_used == 0) { |
|
|
if (fifo_used == 0) { |
|
|
//digitalWriteFast(15, HIGH); |
|
|
//digitalWriteFast(15, HIGH); |
|
|
//delayMicroseconds(2); |
|
|
//delayMicroseconds(2); |
|
|
//digitalWriteFast(15, LOW); |
|
|
//digitalWriteFast(15, LOW); |
|
|
// TODO: this return before the data transmits! |
|
|
|
|
|
|
|
|
// TODO: this returns before the last data transmits! |
|
|
// Should verify every byte ACKs, arbitration not lost |
|
|
// Should verify every byte ACKs, arbitration not lost |
|
|
|
|
|
//printf("fifo empty, msr=%x\n", status); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t length, uint8_t sendStop) |
|
|
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t length, uint8_t sendStop) |
|
|
{ |
|
|
{ |
|
|
uint32_t cmd=0, status, fifo; |
|
|
uint32_t cmd=0, status, fifo; |
|
|
// TODO: sendStop is currently ignored |
|
|
|
|
|
|
|
|
|
|
|
// wait while bus is busy |
|
|
// wait while bus is busy |
|
|
while (1) { |
|
|
while (1) { |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
if (!(LPI2C1_MSR & LPI2C_MSR_BBF)) break; // bus is available |
|
|
|
|
|
if (LPI2C1_MSR & LPI2C_MSR_MBF) break; // we already have bus control |
|
|
|
|
|
|
|
|
if (!(status & LPI2C_MSR_BBF)) break; // bus is available |
|
|
|
|
|
if (status & LPI2C_MSR_MBF) break; // we already have bus control |
|
|
// TODO: timeout... |
|
|
// TODO: timeout... |
|
|
} |
|
|
} |
|
|
printf("idle\n"); |
|
|
|
|
|
|
|
|
//printf("idle2, msr=%x\n", status); |
|
|
|
|
|
|
|
|
// TODO: is this correct if the prior use didn't send stop? |
|
|
// TODO: is this correct if the prior use didn't send stop? |
|
|
LPI2C1_MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF; // clear flags |
|
|
LPI2C1_MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF; // clear flags |
|
|
|
|
|
|
|
|
rxBufferIndex = 0; |
|
|
rxBufferIndex = 0; |
|
|
rxBufferLength = 0; |
|
|
rxBufferLength = 0; |
|
|
|
|
|
|
|
|
|
|
|
//elapsedMillis timeout=0; |
|
|
|
|
|
|
|
|
while (1) { |
|
|
while (1) { |
|
|
// transmit stuff, if we haven't already |
|
|
// transmit stuff, if we haven't already |
|
|
if (cmd < 3) { |
|
|
if (cmd < 3) { |
|
|
fifo = LPI2C1_MFSR & 0x07; // pg 2914 |
|
|
fifo = LPI2C1_MFSR & 0x07; // pg 2914 |
|
|
if (fifo < 4) printf("t=%ld\n", fifo); |
|
|
|
|
|
|
|
|
//if (fifo < 4) printf("t=%ld\n", fifo); |
|
|
while (fifo < 4 && cmd < 3) { |
|
|
while (fifo < 4 && cmd < 3) { |
|
|
if (cmd == 0) { |
|
|
if (cmd == 0) { |
|
|
LPI2C1_MTDR = LPI2C_MTDR_CMD_START | 1 | address; |
|
|
LPI2C1_MTDR = LPI2C_MTDR_CMD_START | 1 | address; |
|
|
|
|
|
|
|
|
// monitor status |
|
|
// monitor status |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
status = LPI2C1_MSR; // pg 2899 & 2892 |
|
|
if (status & LPI2C_MSR_ALF) { |
|
|
if (status & LPI2C_MSR_ALF) { |
|
|
printf("arbitration lost\n"); |
|
|
|
|
|
|
|
|
//printf("arbitration lost\n"); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (status & LPI2C_MSR_NDF) { |
|
|
if (status & LPI2C_MSR_NDF) { |
|
|
printf("got NACK\n"); |
|
|
|
|
|
|
|
|
//printf("got NACK\n"); |
|
|
// TODO: how to make sure stop is sent? |
|
|
// TODO: how to make sure stop is sent? |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//if (timeout > 250) { |
|
|
|
|
|
//printf("Status = %x\n", status); |
|
|
|
|
|
//timeout = 0; |
|
|
|
|
|
//} |
|
|
|
|
|
|
|
|
if (rxBufferLength >= length && cmd >= 3) break; |
|
|
if (rxBufferLength >= length && cmd >= 3) break; |
|
|
} |
|
|
} |
|
|
//digitalWriteFast(15, HIGH); |
|
|
//digitalWriteFast(15, HIGH); |