Skip to content

Instantly share code, notes, and snippets.

@betzrhodes
Last active June 5, 2018 02:00
Show Gist options
  • Save betzrhodes/b3f1afb8daffbc9d78ef0b552a39899d to your computer and use it in GitHub Desktop.
Save betzrhodes/b3f1afb8daffbc9d78ef0b552a39899d to your computer and use it in GitHub Desktop.
MCP2515
// The MCP2515 has three transmit and two receive
// buffers, two acceptance masks (one for each receive
// buffer) and a total of six acceptance filters. Figure 1-3
// shows a block diagram of these buffers and their
// connection to the protocol engine.
// TX Buffer addresses
const MCP2515_TX_BUFF_0_CTRL_REG = 0x30;
const MCP2515_TX_BUFF_1_CTRL_REG = 0x40;
const MCP2515_TX_BUFF_2_CTRL_REG = 0x50;
const MCP2515_TX_RTS_CTRL_STAT_REG = 0x0D;
const MCP2515_TX_BUFF_0_STAND_ID_HIGH = 0x31;
const MCP2515_TX_BUFF_1_STAND_ID_HIGH = 0x41;
const MCP2515_TX_BUFF_2_STAND_ID_HIGH = 0x51;
const MCP2515_TX_BUFF_0_STAND_ID_LOW = 0x32;
const MCP2515_TX_BUFF_1_STAND_ID_LOW = 0x42;
const MCP2515_TX_BUFF_2_STAND_ID_LOW = 0x52;
const MCP2515_TX_BUFF_0_EXTEND_ID_HIGH = 0x33;
const MCP2515_TX_BUFF_1_EXTEND_ID_HIGH = 0x43;
const MCP2515_TX_BUFF_2_EXTEND_ID_HIGH = 0x53;
const MCP2515_TX_BUFF_0_EXTEND_ID_LOW = 0x34;
const MCP2515_TX_BUFF_1_EXTEND_ID_LOW = 0x44;
const MCP2515_TX_BUFF_2_EXTEND_ID_LOW = 0x54;
const MCP2515_TX_BUFF_0_DATA_LEN_CODE = 0x35;
const MCP2515_TX_BUFF_1_DATA_LEN_CODE = 0x45;
const MCP2515_TX_BUFF_2_DATA_LEN_CODE = 0x55;
const MCP2515_TX_BUFF_0_DATA_BYTE_0 = 0x36;
const MCP2515_TX_BUFF_0_DATA_BYTE_1 = 0x37;
const MCP2515_TX_BUFF_0_DATA_BYTE_2 = 0x38;
const MCP2515_TX_BUFF_0_DATA_BYTE_3 = 0x39;
const MCP2515_TX_BUFF_0_DATA_BYTE_4 = 0x3A;
const MCP2515_TX_BUFF_0_DATA_BYTE_5 = 0x3B;
const MCP2515_TX_BUFF_0_DATA_BYTE_6 = 0x3C;
const MCP2515_TX_BUFF_0_DATA_BYTE_7 = 0x3D;
const MCP2515_TX_BUFF_1_DATA_BYTE_0 = 0x46;
const MCP2515_TX_BUFF_1_DATA_BYTE_1 = 0x47;
const MCP2515_TX_BUFF_1_DATA_BYTE_2 = 0x48;
const MCP2515_TX_BUFF_1_DATA_BYTE_3 = 0x49;
const MCP2515_TX_BUFF_1_DATA_BYTE_4 = 0x4A;
const MCP2515_TX_BUFF_1_DATA_BYTE_5 = 0x4B;
const MCP2515_TX_BUFF_1_DATA_BYTE_6 = 0x4C;
const MCP2515_TX_BUFF_1_DATA_BYTE_7 = 0x4D;
const MCP2515_TX_BUFF_2_DATA_BYTE_0 = 0x56;
const MCP2515_TX_BUFF_2_DATA_BYTE_1 = 0x57;
const MCP2515_TX_BUFF_2_DATA_BYTE_2 = 0x58;
const MCP2515_TX_BUFF_2_DATA_BYTE_3 = 0x59;
const MCP2515_TX_BUFF_2_DATA_BYTE_4 = 0x5A;
const MCP2515_TX_BUFF_2_DATA_BYTE_5 = 0x5B;
const MCP2515_TX_BUFF_2_DATA_BYTE_6 = 0x5C;
const MCP2515_TX_BUFF_2_DATA_BYTE_7 = 0x5D;
const MCP2515_RX_BUFF_0_CTRL_REG = 0x60;
const MCP2515_RX_BUFF_1_CTRL_REG = 0x70;
const MCP2515_RX_BUFF_CTRL_STAT_REG = 0x0C;
const MCP2515_RX_BUFF_0_STAND_ID_HIGH = 0x61;
const MCP2515_RX_BUFF_1_STAND_ID_HIGH = 0x71;
const MCP2515_RX_BUFF_0_STAND_ID_LOW = 0x62;
const MCP2515_RX_BUFF_1_STAND_ID_LOW = 0x72;
const MCP2515_RX_BUFF_0_EXTEND_ID_HIGH = 0x63;
const MCP2515_RX_BUFF_1_EXTEND_ID_HIGH = 0x73;
const MCP2515_RX_BUFF_0_EXTEND_ID_LOW = 0x64;
const MCP2515_RX_BUFF_1_EXTEND_ID_LOW = 0x74;
const MCP2515_RX_BUFF_0_DATA_LEN_CODE = 0x65;
const MCP2515_RX_BUFF_1_DATA_LEN_CODE = 0x75;
const MCP2515_RX_BUFF_0_DATA_BYTE_0 = 0x66;
const MCP2515_RX_BUFF_0_DATA_BYTE_1 = 0x67;
const MCP2515_RX_BUFF_0_DATA_BYTE_2 = 0x68;
const MCP2515_RX_BUFF_0_DATA_BYTE_3 = 0x69;
const MCP2515_RX_BUFF_0_DATA_BYTE_4 = 0x6A;
const MCP2515_RX_BUFF_0_DATA_BYTE_5 = 0x6B;
const MCP2515_RX_BUFF_0_DATA_BYTE_6 = 0x6C;
const MCP2515_RX_BUFF_0_DATA_BYTE_7 = 0x6D;
const MCP2515_RX_BUFF_1_DATA_BYTE_0 = 0x76;
const MCP2515_RX_BUFF_1_DATA_BYTE_1 = 0x77;
const MCP2515_RX_BUFF_1_DATA_BYTE_2 = 0x78;
const MCP2515_RX_BUFF_1_DATA_BYTE_3 = 0x79;
const MCP2515_RX_BUFF_1_DATA_BYTE_4 = 0x7A;
const MCP2515_RX_BUFF_1_DATA_BYTE_5 = 0x7B;
const MCP2515_RX_BUFF_1_DATA_BYTE_6 = 0x7C;
const MCP2515_RX_BUFF_1_DATA_BYTE_7 = 0x7D;
const MCP2515_RX_FILTER_0_STAND_ID_HIGH = 0x00;
const MCP2515_RX_FILTER_1_STAND_ID_HIGH = 0x04;
const MCP2515_RX_FILTER_2_STAND_ID_HIGH = 0x08;
const MCP2515_RX_FILTER_3_STAND_ID_HIGH = 0x10;
const MCP2515_RX_FILTER_4_STAND_ID_HIGH = 0x14;
const MCP2515_RX_FILTER_5_STAND_ID_HIGH = 0x18;
const MCP2515_RX_FILTER_0_STAND_ID_LOW = 0x01;
const MCP2515_RX_FILTER_1_STAND_ID_LOW = 0x05;
const MCP2515_RX_FILTER_2_STAND_ID_LOW = 0x09;
const MCP2515_RX_FILTER_3_STAND_ID_LOW = 0x11;
const MCP2515_RX_FILTER_4_STAND_ID_LOW = 0x15;
const MCP2515_RX_FILTER_5_STAND_ID_LOW = 0x19;
const MCP2515_RX_FILTER_0_EXTEND_ID_HIGH = 0x02;
const MCP2515_RX_FILTER_1_EXTEND_ID_HIGH = 0x06;
const MCP2515_RX_FILTER_2_EXTEND_ID_HIGH = 0x0A;
const MCP2515_RX_FILTER_3_EXTEND_ID_HIGH = 0x12;
const MCP2515_RX_FILTER_4_EXTEND_ID_HIGH = 0x16;
const MCP2515_RX_FILTER_5_EXTEND_ID_HIGH = 0x1A;
const MCP2515_RX_FILTER_0_EXTEND_ID_LOW = 0x03;
const MCP2515_RX_FILTER_1_EXTEND_ID_LOW = 0x07;
const MCP2515_RX_FILTER_2_EXTEND_ID_LOW = 0x0B;
const MCP2515_RX_FILTER_3_EXTEND_ID_LOW = 0x13;
const MCP2515_RX_FILTER_4_EXTEND_ID_LOW = 0x17;
const MCP2515_RX_FILTER_5_EXTEND_ID_LOW = 0x1B;
const MCP2515_RX_MASK_0_STAND_ID_HIGH = 0x20;
const MCP2515_RX_MASK_1_STAND_ID_HIGH = 0x24;
const MCP2515_RX_MASK_0_STAND_ID_LOW = 0x21;
const MCP2515_RX_MASK_1_STAND_ID_LOW = 0x25;
const MCP2515_RX_MASK_0_EXTEND_ID_HIGH = 0x22;
const MCP2515_RX_MASK_1_EXTEND_ID_HIGH = 0x26;
const MCP2515_RX_MASK_0_EXTEND_ID_LOW = 0x23;
const MCP2515_RX_MASK_1_EXTEND_ID_LOW = 0x27;
const MCP2515_CONFIG_REG_1 = 0x2A;
const MCP2515_CONFIG_REG_2 = 0x29;
const MCP2515_CONFIG_REG_3 = 0x28;
const MCP2515_TX_ERROR_COUNT_REG = 0x1C;
const MCP2515_RX_ERROR_COUNT_REG = 0x1D;
const MCP2515_ERROR_FLAG_REG = 0x2D;
const MCP2515_CAN_INT_EN_REG = 0x2B;
const MCP2515_CAN_INT_FLAG_REG = 0x2C;
const MCP2515_CAN_CTRL_REG = 0x0F;
const MCP2515_CAN_STATUS_REG = 0x0E;
// SPI Instructions
const MCP2515_CMD_RESET = 0xC0;
const MCP2515_CMD_READ = 0x03;
const MCP2515_CMD_WRITE = 0x02;
const MCP2515_CMD_READ_STATUS = 0xA0;
const MCP2515_CMD_RX_STATUS = 0xB0;
const MCP2515_CMD_BIT_MODIFY = 0x05;
const MCP2515_CMD_READ_RX_BUFF_0 = 0x90;
const MCP2515_CMD_READ_RX_BUFF_1 = 0x94;
const MCP2515_CMD_LOAD_TX_BUFF_0 = 0x40;
const MCP2515_CMD_LOAD_TX_BUFF_1 = 0x42;
const MCP2515_CMD_LOAD_TX_BUFF_2 = 0x44;
const MCP2515_CMD_RTS_TX_0 = 0x81;
const MCP2515_CMD_RTS_TX_1 = 0x82;
const MCP2515_CMD_RTS_TX_2 = 0x84;
const MCP2515_CMD_RTS_TX_ALL = 0x87;
// Modes of Operation
const MCP2515_OP_MODE_MASK = 0xE0;
const MCP2515_OP_MODE_NORMAL = 0x00;
const MCP2515_OP_MODE_SLEEP = 0x20;
const MCP2515_OP_MODE_LOOPBACK = 0x40;
const MCP2515_OP_MODE_LISTEN_ONLY = 0x60;
const MCP2515_OP_MODE_CONFIG = 0x80;
const MCP2515_OP_MODE_POWERUP = 0xE0;
class MCP2515 {
_spi = null;
_cs = null;
_int = null;
_mode = null;
constructor(spi, cs = null, intPin = null) {
_spi = spi; // spiBCAD on FB gateway
_cs = cs; // pinD on FB gateway
_int = intPin; // pinXD on FB gateway
// Add reset pin??
if (_cs != null) _cs.configure(DIGITAL_OUT, 1);
// TODO: configure interrupt pin
}
// Reinitializes the internal registers
// After reset MCP2515 will be in config op mode
// Sending reset cmd is the same as using the reset pin
// Recommended to call reset during power-on/init seq.
function reset() {
local data = blob(1);
data.writen(MCP2515_CMD_RESET, 'b');
(_cs) ? _cs.write(0) : _spi.chipselect(1);
_spi.writeread(data);
(_cs) ? _cs.write(1) : _spi.chipselect(0);
imp.sleep(0.1);
}
// Declare controller initialization parameters
// enMaskFilt - sets the RX buffer id mode
// Baud rate preScaler, prop seg, phase seg 1, phase seg 2 (min val is 2), SJW (default 1)
function init(enMaskFilt, BRP, propSeg, phaseSeg1, phaseSeg2, SJW = 1) {
// Reset to default state
reset();
// Set chip into config mode (shouldn't be needed based on datasheet reset info)
local res = _getReg(MCP2515_CAN_STATUS_REG);
if ((res[0] & MCP2515_OP_MODE_MASK) != MCP2515_OP_MODE_CONFIG) setOpMode(MCP2515_OP_MODE_CONFIG);
// TODO: check result for errors before continuing
// server.log(res);
// Set Configuration filters
// Note: Register values are one less than the actual values for BRP, propSeg,
// phaseSeg1, phaseSeg2, and SJW
// Config settings not exposed by init:
// PhaseSeg2 determined by CONFIG_REG_3 (1)
// Sample Point 3X (1)
// CLKOUT pin is enabled for Start-of-Frame signal (1)
// Wakeup Filter bit enabled
// MCP2515_CONFIG_REG_1 - SJW - 1 = (6-7), BRP - 1 = (5-0)
// MCP2515_CONFIG_REG_2 - BTLMODE(7) = 1, SAM(6) = 1, Phase1Seg - 1 (3-5), PropSeg - 1 (0-2)
// MCP2515_CONFIG_REG_3 - SOF(7) = 1, WAKFIL(6) = 0, NA(5-3) = 0, Phase2Seg - 1 (0-2)
// Set Config Reg 1
local val = (SJW - 1) << 6 | (BRP - 1);
res = _writeReg(MCP2515_CONFIG_REG_1, val);
// server.log(res);
val = 0xC0 | (propSeg - 1) << 3 | (phaseSeg1 - 1);
res = _writeReg(MCP2515_CONFIG_REG_2, val);
// server.log(res);
val = 0x80 | (phaseSeg2 - 1);
res = _writeReg(MCP2515_CONFIG_REG_3, val);
// server.log(res);
// TODO: check result for errors before continuing
// Initialize Buffers, Masks and Filters (set all filter and mask reg to 0x00)
val = _createZeroFilledBlob(12);
res = _writeReg(MCP2515_RX_FILTER_0_STAND_ID_HIGH, val);
// server.log(res);
res = _writeReg(MCP2515_RX_FILTER_3_STAND_ID_HIGH, val);
// server.log(res);
val = _createZeroFilledBlob(8);
res = _writeReg(MCP2515_RX_MASK_0_STAND_ID_HIGH, val);
// server.log(res);
// TODO: check result for errors before continuing
// Clear TX Buffers (30 40 50 60 70)
val = _createZeroFilledBlob(13);
res = _writeReg(MCP2515_TX_BUFF_0_CTRL_REG, val);
// server.log(res);
res = _writeReg(MCP2515_TX_BUFF_1_CTRL_REG, val);
// server.log(res);
res = _writeReg(MCP2515_TX_BUFF_2_CTRL_REG, val);
// server.log(res);
// Clear RX Ctrl Buffers
res = _writeReg(MCP2515_RX_BUFF_0_CTRL_REG, 0x00);
// server.log(res);
res = _writeReg(MCP2515_RX_BUFF_1_CTRL_REG, 0x00);
// server.log(res);
// Enable interrupt when RX buffer full
res = _writeReg(MCP2515_CAN_INT_EN_REG, 0x03);
// server.log(res);
// Configure RX Buffer to Digital output mode
res = _writeReg(MCP2515_RX_BUFF_CTRL_STAT_REG, 0x3C);
// server.log(res);
// Disable TX request to send mode
res = _writeReg(MCP2515_TX_RTS_CTRL_STAT_REG, 0x00);
// server.log(res);
// TODO: check result for errors before continuing
// Enable msg filtering
if (enMaskFilt) {
res = _modifyReg(MCP2515_RX_BUFF_0_CTRL_REG, 0x64, 0x00);
// server.log(res)
res = _modifyReg(MCP2515_RX_BUFF_1_CTRL_REG, 0x60, 0x00);
// server.log(res);
} else {
res = _modifyReg(MCP2515_RX_BUFF_0_CTRL_REG, 0x64, 0x60);
// server.log(res);
res = _modifyReg(MCP2515_RX_BUFF_1_CTRL_REG, 0x60, 0x60);
// server.log(res);
}
// TODO: check result for errors before continuing
// Set Can Control Mode To Loopback (ie not config)
res = setOpMode(MCP2515_OP_MODE_LOOPBACK);
// server.log(res);
// TODO: check result for errors before continuing
}
function setOpMode(mode) {
local res = _modifyReg(MCP2515_CAN_CTRL_REG, MCP2515_OP_MODE_MASK, mode);
_mode = _getReg(MCP2515_CAN_STATUS_REG)[0] & MCP2515_OP_MODE_MASK;
return _mode;
}
// NOTE: Mask 0 - is mask for buffer 0, mask 1 is mask for buffer 1
function configureMask(maskNum, id) {
local ext = (id.len() > 11);
switch (maskNum) {
case 0:
_configureMasksAndFilters(MCP2515_RX_MASK_0_STAND_ID_HIGH, ext, id);
break;
case 1:
_configureMasksAndFilters(MCP2515_RX_MASK_1_STAND_ID_HIGH, ext, id);
break;
default:
// Invalid mask number
break;
}
}
// NOTE: Filters 0 & 1 filter buffer 0, filters 2 - 5 filter buffer 1
function configureFilter(filterNum, ext, id) {
switch (filterNum) {
case 0:
_configureMasksAndFilters(MCP2515_RX_FILTER_0_STAND_ID_HIGH, ext, id);
break;
case 1:
_configureMasksAndFilters(MCP2515_RX_FILTER_1_STAND_ID_HIGH, ext, id);
break;
case 2:
_configureMasksAndFilters(MCP2515_RX_FILTER_2_STAND_ID_HIGH, ext, id);
break;
case 3:
_configureMasksAndFilters(MCP2515_RX_FILTER_3_STAND_ID_HIGH, ext, id);
break;
case 4:
_configureMasksAndFilters(MCP2515_RX_FILTER_4_STAND_ID_HIGH, ext, id);
break;
case 5:
_configureMasksAndFilters(MCP2515_RX_FILTER_5_STAND_ID_HIGH, ext, id);
break;
default:
// Invalid filter number
break;
}
}
// function sendMsg() {}
function readMsg() {
// Check for msgs in buffer 0 and 1
local status = _readStatus();
// server.log(format("0x%02X", status));
local msg = null;
if (status & 0x01) {
server.log("We have msg in buffer 0");
// get message, clear interrupt flag
msg = _readMsgFromBuffer(MCP2515_RX_BUFF_0_CTRL_REG);
_modifyReg(MCP2515_CAN_INT_FLAG_REG, 0x01, 0x00);
} else if (status & 0x02) {
server.log("We have msg in buffer 1");
// get message, clear interrupt flag
msg = _readMsgFromBuffer(MCP2515_RX_BUFF_1_CTRL_REG);
_modifyReg(MCP2515_CAN_INT_FLAG_REG, 0x02, 0x00);
} else {
server.log("No msg found.");
// msg = _readMsgFromBuffer(MCP2515_RX_BUFF_0_CTRL_REG);
// local msg1 = _readMsgFromBuffer(MCP2515_RX_BUFF_1_CTRL_REG);
}
return msg;
}
function getError() {
local res = _getReg(MCP2515_ERROR_FLAG_REG);
if (typeof res == "blob" && res.len() == 1) {
local errorFlagReg = res[0];
// server.log(errorFlagReg);
if (errorFlagReg == 0) server.log("No errors found");
if (errorFlagReg & 0x01) server.log("RX Buffer 1 overflow");
if (errorFlagReg & 0x02) server.log("RX Buffer 0 overflow");
if (errorFlagReg & 0x04) server.log("TX Bus off");
if (errorFlagReg & 0x08) server.log("TX Error Passive");
if (errorFlagReg & 0x10) server.log("RX Error Passive");
if (errorFlagReg & 0x20) server.log("TX Error Warning");
if (errorFlagReg & 0x40) server.log("RX Error Warning");
if (errorFlagReg & 0x80) server.log("TX or RX Error Warning");
}
}
function _configureMasksAndFilters(startingAddr, ext, id) {
local data = blob(4);
// 0 = Standard High reg data (bits 3-10 of standard id)
// 1 = Standard Low reg data (bits 0-2 of standard id, ext filter enable, and bits 16-17 ext id)
// 2 = Extened High reg data (bits 8-15 of ext id)
// 3 = Extended Low reg data (bits 0-7 of ext id)
// Note: Each filter/mask id will be written to both the standard and
// extened registers, unkown bits will be set to 0 (no mask/filter)
// 0 | 0000 | 0000 | 0000 | 0000 | 0 ** 000 | 0000 | 0000 |
// | 0 ** 111 | 1111 | 1000 |
// | 0111 |
// 0 | 0000 | 0000 | 0000 | 0000 | 0 ** 000 | 0000 | 0000 |
// | 0111 | 1111 | 1000 | 0000 | 0 ** 000 | 0000 | 0000 |
// | 0111 | 1111 | 1 ** 000 | 0000 | 0000 |
// 1 | 1000 | 0000 | 0000 | 0000 | 0 ** 000 | 0000 | 0000 |
// Top bits of Standard id (grab bits 3-10 of id)
data[0] = (id & 0x7F8) >> 3;
// Mid bits of Extended id (grab bits 8-15 of id)
data[2] = (id & 0x7F80000) >> 19;
// Lower bits of Extended id (grab bits 0-7 of id)
data[3] = id & 0x7F800 >> 11;
// If ext filter enabled write 1 to reg bit 3
local extEn = (ext) ? 1 : 0;
// Lower bits stand (grab 0-2 of id) write to reg bits 5-7,
// Top bits Ext (grab 16-17 of id) write to reg bits 0-1,
data[1] = (id & 0x07) << 5 | extEn << 3 | (id << 27) & 0x03;
// Set to configure mode
local res = setOpMode(MCP2515_OP_MODE_CONFIG);
// Update register
res = _writeReg(startingAddr, data);
// Set back to non-config mode
res = setOpMode(_mode);
}
function _readMsgFromBuffer(buffCtrlAddr) {
local res = _getReg(buffCtrlAddr, 6);
server.log("Get readMsg response: ");
server.log(res);
// [0] - CTRL, [1] - StandId high, [2] - StandId low
// [3] - ExtId high, [4] - ExtId low, [5] - Data len
// 0x-0 - (3) remote transfer requested
// 0x-1 - stand id high (3-10)
// 0x-2 - (0-1) ext id MSB (16-17),
// (3) extend flag ext = 1, stand = 0,
// (4) stand frame remote=1,
// (5-7) stand id (0-2)
// 0x-3 - extended id high (8-15)
// 0x-4 - extended id low (0-7)
// 0x-5 - (0-3) data length,
// (6) extended frame remote=1,
local rtr;
local ext = (res[2] & 0x08) == 1;
local dataLen = res[5] & 0x0F;
// Grab the Standard ID
local id = res[1] << 3 | (res[2] & 0xE0) >> 5
// Remote transfer request received
local rtrReceived = (res[0] & 0x08) == 1;
if (ext) {
// We have an extended frame msg
// Remote transmit requested
rtr = (res[5] & 0x40) == 1;
// Update msg ID to include extended ID
id = (res[2] & 0x03) << 27 | res[3] << 19 | res[4] << 11 | id;
} else {
// We have a standard frame msg, check remote transmit request
rtr = (res[2] & 0x10) == 1;
}
// Read data out of buffer
local data = _getReg(buffCtrlAddr + 6, dataLen);
return {"extended" : ext, "rtr" : rtr, "rtrReceived" : rtrReceived, "id" : id, "msg" : data};
}
function _writeReg(addr, val) {
local data = blob();
data.writen(MCP2515_CMD_WRITE, 'b');
data.writen(addr, 'b');
if (typeof val == "blob") {
data.writeblob(val);
} else {
data.writen(val, 'b');
}
(_cs) ? _cs.write(0) : _spi.chipselect(1);
local res = _spi.writeread(data);
(_cs) ? _cs.write(1) : _spi.chipselect(0);
return res;
}
function _getReg(addr, numBytes = 1) {
local data = blob();
data.writen(MCP2515_CMD_READ, 'b');
data.writen(addr, 'b');
for (local i = 0; i < numBytes; i++) {
data.writen(0x00, 'b');
}
(_cs) ? _cs.write(0) : _spi.chipselect(1);
local res = _spi.writeread(data);
(_cs) ? _cs.write(1) : _spi.chipselect(0);
res.seek(2, 'b');
return (numBytes > 0) ? res.readblob(numBytes) : null;
}
function _modifyReg(addr, mask, val) {
local data = blob(4);
data.writen(MCP2515_CMD_BIT_MODIFY, 'b');
data.writen(addr, 'b');
data.writen(mask, 'b');
data.writen(val, 'b');
(_cs) ? _cs.write(0) : _spi.chipselect(1);
local res = _spi.writeread(data);
(_cs) ? _cs.write(1) : _spi.chipselect(0);
return res;
}
function _readStatus() {
local data = blob();
data.writen(MCP2515_CMD_READ_STATUS, 'b');
data.writen(0xFF, 'b');
(_cs) ? _cs.write(0) : _spi.chipselect(1);
local res = _spi.writeread(data);
(_cs) ? _cs.write(1) : _spi.chipselect(0);
return res[1];
}
function _createZeroFilledBlob(length) {
local b = blob(length);
for (local i = 0; i < b.len(); i++) {
b.writen(0x00, 'b');
}
return b;
}
}
function logRes(res) {
foreach (k, v in res) {
if (typeof v != "blob") {
server.log(k + ": " + v);
} else {
server.log(k);
server.log(v);
}
}
}
spi <- hardware.spiBCAD;
int <- hardware.pinXD;
// Mode 00
spi.configure(CLOCK_IDLE_LOW, 1000);
int.configure(DIGITAL_IN, function() {
local r = int.read();
// server.log("Interrupt Pin state: " + r);
if (!r) getMsg();
})
can <- MCP2515(spi, hardware.pinD, hardware.pinXD);
// Settings based on 10mHz clock, data tx speed 1Mbps
// Disable masks and filters, BRP = 1, propSeg = 1, phaseSeg1 = 1, phaseSeg2 = 2, SJW = 1
can.init(false, 1, 1, 1, 2, 1); //1Mb/s
// can.init(false, 1, 2, 4, 3, 1); //500kb/s
can.setOpMode(MCP2515_OP_MODE_NORMAL);
can.getError();
imp.sleep(5);
function getMsg() {
// Get message:
server.log("--------------------------")
local msg = can.readMsg();
// Log response and if none check buffers anyway!!!
if (msg != null) {
logRes(msg);
if (msg.msg == null) can.getError();
} else {
server.log("No msg available");
server.log("-------------------");
server.log("RX0 CTRL and Buffer: ");
local res0 = can._readMsgFromBuffer(MCP2515_RX_BUFF_0_CTRL_REG);
logRes(res0);
server.log("-------------------");
server.log("RX1 CTRL and Buffer: ");
local res1 = can._readMsgFromBuffer(MCP2515_RX_BUFF_1_CTRL_REG);
logRes(res1);
}
server.log("--------------------------");
// imp.wakeup(5, getMsg);
};
// getMsg();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment