diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2025-10-03 17:33:55 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2025-10-03 17:33:55 -0400 |
| commit | 94b454765086cfaddee63921ac1f2d9b5598a762 (patch) | |
| tree | d8473a4618928037f5e8beac3643cb5b7ad3e603 /fw/can.c | |
| parent | 31937ab63b897b8092df64675a717a5b93d4d5dc (diff) | |
| download | can-gauge-interface-94b454765086cfaddee63921ac1f2d9b5598a762.zip | |
mcp2515 spi functions
Diffstat (limited to 'fw/can.c')
| -rw-r--r-- | fw/can.c | 131 |
1 files changed, 127 insertions, 4 deletions
@@ -2,14 +2,30 @@ #include <stdint.h> +#include "system.h" #include "types.h" +#include "spi.h" #include "can.h" +// Oscillator startup timeout +#define STARTUP_TIME 128u + // Register addresses enum { - // Pin control and status - REG_BFPCTRL = 0x0C, + // Config + REG_BFPCTRL = 0x0C, // pin control and status + REG_CANCTRL = 0x0F, // CAN control + REG_CANSTAT = 0x0E, // CAN status + + // Bit timing + REG_CNF1 = 0x2A, + REG_CNF2 = 0x29, + REG_CNF3 = 0x28, + + // Interrupts + REG_CANINTE = 0x2B, // CAN interrupt enable + REG_CANINTF = 0x2C, // CAN interrupt flag // Filter 0 REG_RXF0SIDH = 0x00, // standard ID high @@ -48,7 +64,7 @@ enum { REG_RXF5EID0 = 0x1B, // extended ID low // Mask 0 - REG_RXM0SIDH = 0x20, standard ID high + REG_RXM0SIDH = 0x20, // standard ID high REG_RXM0SIDL = 0x21, // standard ID low REG_RXM0EID8 = 0x22, // extended ID high REG_RXM0EID0 = 0x23, // extended ID low @@ -56,7 +72,7 @@ enum { // Mask 1 REG_RXM1SIDH = 0x24, // standard ID high REG_RXM1SIDL = 0x25, // standard ID low - REG_RXM1EID8 = 0x26. // extended ID high + REG_RXM1EID8 = 0x26, // extended ID high REG_RXM1EID0 = 0x27, // extended ID low // Receive buffer 0 @@ -77,3 +93,110 @@ enum { REG_RXB1DLC = 0x75, // data length code REG_RXB1DM = 0x76, // data byte <M> [76h+0, 76h+7] }; + +// Modes of operation +typedef enum { + MODE_NORMAL = 0x0, + MODE_SLEEP = 0x1, + MODE_LOOPBACK = 0x2, + MODE_LISTEN_ONLY = 0x3, + MODE_CONFIG = 0x4, +} Mode; + +// Instructions +enum { + CMD_RESET = 0xC0, + CMD_READ = 0x03, + CMD_READ_RX = 0x90, + CMD_WRITE = 0x02, + CMD_LOAD_TX = 0x40, + CMD_RTS = 0x80, + CMD_READ_STATUS = 0xA0, + CMD_RX_STATUS = 0xB0, + CMD_BIT_MODIFY = 0x05, +}; + +// Receive buffer identifiers +typedef enum { + RXB0 = 0, + RXB1 = 1, +} RxBuf; + +// Send RESET instruction. +static void +reset(void) { + CAN_CS = 0; + (void)spiTx(CMD_RESET); + CAN_CS = 1; +} + +// Read n registers into data, starting at the specified address. +static void +read(U8 addr, U8 *data, U8 n) { + CAN_CS = 0; + (void)spiTx(CMD_READ); + (void)spiTx(addr); + while (n--) { + *data = spiTx(0x00); + data++; + } + CAN_CS = 1; +} + +// Read the DATA field of one of the RX buffers. +static void +readRxData(RxBuf bufNum, U8 data[8u]) { + U8 i; + + CAN_CS = 0; + (void)spiTx(CMD_READ_RX | (U8)(bufNum << 2u) | 1u); // start at RXBnD0 + for (i = 0u; i < 8u; i++) { + data[i] = spiTx(0x00); + } + CAN_CS = 1; +} + +// Write to a register. +static void +write(U8 addr, U8 data) { + CAN_CS = 0; + (void)spiTx(CMD_WRITE); + (void)spiTx(addr); + (void)spiTx(data); + CAN_CS = 1; +} + +// Read RX status. +static U8 +rxStatus(void) { + U8 status; + + CAN_CS = 0; + (void)spiTx(CMD_RX_STATUS); + status = spiTx(0x00); + CAN_CS = 1; + return status; +} + +// Write individual bits of a register with the BIT MODIFY instruction. +static void +bitModify(U8 addr, U8 mask, U8 data) { + CAN_CS = 0; + (void)spiTx(CMD_BIT_MODIFY); + (void)spiTx(addr); + (void)spiTx(mask); + (void)spiTx(data); + CAN_CS = 1; +} + +void +canInit(void) { + CAN_CS_TRIS = OUT; + CAN_CS = 1; + + _delay(STARTUP_TIME); // wait for MCP2515 to power on + reset(); // send RESET command + _delay(STARTUP_TIME); // wait to power on again + + // TODO +} |