aboutsummaryrefslogtreecommitdiffstats
path: root/fw/can.h
blob: 621b20f7b1fc1d30359a57949ad21982ed876226 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* Microchip MCP2515 CAN Controller
 *
 * Device: PIC16F1459
 * Compiler: XC8 v3.00
 *
 * MCP2515 FOSC = 12MHz (48MHz/4 from PIC's CLKOUT)
 *
 * Usage:
 *
 * #include <xc.h>
 * #include <stdbool.h>
 * #include <stdint.h>
 * #include "types.h"
 * #include "can.h"
 */

// Pin mapping
#define CAN_CS_TRIS TRISAbits.TRISA5
#define CAN_CS LATAbits.LATA5

// Bit timings (CNF1, CNF2, CNF3)
#define CAN_TIMING_10K 0xDD, 0xAD, 0x06 // BRP=30, PropSeg=6, PS1=6, PS2=7, SP=65%, SJW=4
#define CAN_TIMING_20K 0xCE, 0xAD, 0x06 // BRP=15, PropSeg=6, PS1=6, PS2=7, SP=65%, SJW=4
#define CAN_TIMING_50K 0xC5, 0xAD, 0x06 // BRP=6, PropSeg=6, PS1=6, PS2=7, SP=65%, SJW=4
#define CAN_TIMING_100K 0xC2, 0xAD, 0x06 // BRP=3, PropSeg=6, PS1=6, PS2=7, SP=65%, SJW=4
#define CAN_TIMING_125K 0xC3, 0x9A, 0x03 // BRP=4, PropSeg=3, PS1=4, PS2=4, SP=66.7%, SJW=4
#define CAN_TIMING_250K 0xC1, 0x9A, 0x03 // BRP=2, PropSeg=3, PS1=4, PS2=4, SP=66.7%, SJW=4
#define CAN_TIMING_500K 0xC0, 0x9A, 0x03 // BRP=1, PropSeg=3, PS1=4, PS2=4, SP=66.7%, SJW=4
#define CAN_TIMING_800K "800kbps unsupported" // not possible with 12MHz clock
#define CAN_TIMING_1M "1Mbps unsupported" // not possible with 12MHz clock

// MCP2515 modes of operation
typedef enum {
	CAN_MODE_NORMAL = 0x0,
	CAN_MODE_SLEEP = 0x1,
	CAN_MODE_LOOPBACK = 0x2,
	CAN_MODE_LISTEN_ONLY = 0x3,
	CAN_MODE_CONFIG = 0x4,
} CanMode;

// CAN identifier
typedef struct {
	bool isExt; // is extended
	union {
		U16 sid; // 11-bit standard ID -- ID[28:18]
		U32 eid; // 29-bit extended ID -- ID[28:0]
	};
} CanId;

// CAN frame
typedef struct {
	CanId id;
	bool rtr; // remote transmission request
	U8 dlc; // data length code
	U8 data[8];
} CanFrame;

// Initialize the MCP2515.
// Initial mode is Config.
void canInit(void);

// Set the operating mode of the MCP2515.
void canSetMode(CanMode mode);

// Set the bit timing parameters (bitrate, etc.).
// Pass one of the CAN_TIMING_x macros.
// The MCP2515 must be in Config mode.
void canSetBitTiming(U8 cnf1, U8 cnf2, U8 cnf3);

// Enable/disable RX-buffer-full interrupts on the MCP2515's INT pin.
void canIE(bool enable);

// Read RX status with RX STATUS instruction.
U8 canRxStatus(void);

// Read the frame in RXB0.
void canReadRxb0(CanFrame *frame);

// Read the frame in RXB1.
void canReadRxb1(CanFrame *frame);

// Transmit a frame to the CAN bus
Status canTx(const CanFrame *frame);

// Set the message acceptance mask of RXB0.
// The MCP2515 must be in Config mode.
void canSetMask0(const CanId *mask);

// Set the message acceptance mask of RXB1.
// The MCP2515 must be in Config mode.
void canSetMask1(const CanId *mask);

// Set message acceptance filter 0 (RXB0).
// The MCP2515 must be in Config mode.
void canSetFilter0(const CanId *filter);

// Set message acceptance filter 1 (RXB0).
// The MCP2515 must be in Config mode.
void canSetFilter1(const CanId *filter);

// Set message acceptance filter 2 (RXB1).
// The MCP2515 must be in Config mode.
void canSetFilter2(const CanId *filter);

// Set message acceptance filter 3 (RXB1).
// The MCP2515 must be in Config mode.
void canSetFilter3(const CanId *filter);

// Set message acceptance filter 4 (RXB1).
// The MCP2515 must be in Config mode.
void canSetFilter4(const CanId *filter);

// Set message acceptance filter 5 (RXB1).
// The MCP2515 must be in Config mode.
void canSetFilter5(const CanId *filter);