aboutsummaryrefslogtreecommitdiffstats
path: root/fw/can.c
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2025-10-03 17:33:55 -0400
committerSam Anthony <sam@samanthony.xyz>2025-10-03 17:33:55 -0400
commit94b454765086cfaddee63921ac1f2d9b5598a762 (patch)
treed8473a4618928037f5e8beac3643cb5b7ad3e603 /fw/can.c
parent31937ab63b897b8092df64675a717a5b93d4d5dc (diff)
downloadcan-gauge-interface-94b454765086cfaddee63921ac1f2d9b5598a762.zip
mcp2515 spi functions
Diffstat (limited to 'fw/can.c')
-rw-r--r--fw/can.c131
1 files changed, 127 insertions, 4 deletions
diff --git a/fw/can.c b/fw/can.c
index b005fc2..b311383 100644
--- a/fw/can.c
+++ b/fw/can.c
@@ -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
+}