Skip to content

Commit 828a145

Browse files
committed
Optimize MCP2515Class::parsePacket()
1) Use the RX STATUS command instead of READ(CANINTF) to check availability of data to read. This reduces SPI usage for a simple "is data available" check from 3 bytes to 2. 2) Use the READ RX BUFFER command to read the RXFn* registers as well as the received data. This requires doing only a single CS pull, and only N+6 bytes transferred over SPI. READ RX BUFFER also takes care of resetting the RXnIF flag. If my math is right, the old code needed N+6 readRegister() calls for a standard frame, and N+9 readRegister() calls for an extended frame, plus one modifyRegister() call to reset the RXnIF flag. Each readRegister() call requires a CS pull and transferring 3 bytes over SPI. For N = 8, - we now send 16 bytes over SPI vs 45 for a standard frame (>2.8x reduction!) - we now do just 2 CS pulls vs 16 for a standard frame (8x reduction!)
1 parent bcdd7ac commit 828a145

File tree

1 file changed

+41
-16
lines changed

1 file changed

+41
-16
lines changed

src/MCP2515.cpp

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -212,49 +212,74 @@ int MCP2515Class::endPacket()
212212

213213
int MCP2515Class::parsePacket()
214214
{
215-
int n;
216-
217-
uint8_t intf = readRegister(REG_CANINTF);
215+
SPI.beginTransaction(_spiSettings);
216+
digitalWrite(_csPin, LOW);
217+
SPI.transfer(0xb0); // RX STATUS
218+
uint8_t rxStatus = SPI.transfer(0x00);
219+
digitalWrite(_csPin, HIGH);
220+
SPI.endTransaction();
218221

219-
if (intf & FLAG_RXnIF(0)) {
222+
int n;
223+
if (rxStatus & 0x40) {
220224
n = 0;
221-
} else if (intf & FLAG_RXnIF(1)) {
225+
} else if (rxStatus & 0x80) {
222226
n = 1;
223227
} else {
224228
_rxId = -1;
225229
_rxExtended = false;
226230
_rxRtr = false;
231+
_rxDlc = 0;
232+
_rxIndex = 0;
227233
_rxLength = 0;
228234
return 0;
229235
}
230236

231-
_rxExtended = (readRegister(REG_RXBnSIDL(n)) & FLAG_IDE) ? true : false;
232-
233-
uint32_t idA = ((readRegister(REG_RXBnSIDH(n)) << 3) & 0x07f8) | ((readRegister(REG_RXBnSIDL(n)) >> 5) & 0x07);
237+
SPI.beginTransaction(_spiSettings);
238+
digitalWrite(_csPin, LOW);
239+
// Send READ RX BUFFER instruction to sequentially read registers, starting
240+
// from RXBnSIDH(n).
241+
SPI.transfer(0b10010000 | (n * 0x04));
242+
uint8_t regSIDH = SPI.transfer(0x00);
243+
uint8_t regSIDL = SPI.transfer(0x00);
244+
_rxExtended = (regSIDL & FLAG_IDE) ? true : false;
245+
246+
// We could just skip the extended registers for standard frames, but that
247+
// would actually add more overhead, and increase complexity.
248+
uint8_t regEID8 = SPI.transfer(0x00);
249+
uint8_t regEID0 = SPI.transfer(0x00);
250+
uint8_t regDLC = SPI.transfer(0x00);
251+
uint32_t idA = (regSIDH << 3) | (regSIDL >> 5);
234252
if (_rxExtended) {
235-
uint32_t idB = (((uint32_t)(readRegister(REG_RXBnSIDL(n)) & 0x03) << 16) & 0x30000) | ((readRegister(REG_RXBnEID8(n)) << 8) & 0xff00) | readRegister(REG_RXBnEID0(n));
253+
uint32_t idB =
254+
((uint32_t)(regSIDL & 0x03) << 16)
255+
| ((uint32_t)regEID8 << 8)
256+
| regEID0;
236257

237258
_rxId = (idA << 18) | idB;
238-
_rxRtr = (readRegister(REG_RXBnDLC(n)) & FLAG_RTR) ? true : false;
259+
_rxRtr = (regDLC & FLAG_RTR) ? true : false;
239260
} else {
240261
_rxId = idA;
241-
_rxRtr = (readRegister(REG_RXBnSIDL(n)) & FLAG_SRR) ? true : false;
262+
_rxRtr = (regSIDL & FLAG_SRR) ? true : false;
242263
}
243-
_rxDlc = readRegister(REG_RXBnDLC(n)) & 0x0f;
264+
265+
_rxDlc = regDLC & 0x0f;
244266
_rxIndex = 0;
245267

246268
if (_rxRtr) {
247269
_rxLength = 0;
248270
} else {
249271
_rxLength = _rxDlc;
250272

251-
for (int i = 0; i < _rxLength; i++) {
252-
_rxData[i] = readRegister(REG_RXBnD0(n) + i);
273+
// Get the data.
274+
for (uint8_t i = 0; i < _rxLength; i++) {
275+
_rxData[i] = SPI.transfer(0x00);
253276
}
254277
}
255278

256-
modifyRegister(REG_CANINTF, FLAG_RXnIF(n), 0x00);
257-
279+
// Don't need to unset the RXnIF(n) flag as this is done automatically when
280+
// setting the CS high after a READ RX BUFFER instruction.
281+
digitalWrite(_csPin, HIGH);
282+
SPI.endTransaction();
258283
return _rxDlc;
259284
}
260285

0 commit comments

Comments
 (0)