2 # GoodFET MCP2515 CAN Bus Client
4 # (C) 2012 Travis Goodspeed <travis at radiantmachines.com>
7 # Currently being updated by Siege Technology's ENGS89 team
8 # Primary contact: Theodore Sumers <ted.sumers at gmail.com>
10 # 10.4/41.6/83.3 kHz sniffing
12 # debugs on TX and RX packet
13 # int-based state change reqs for preserving state
16 # The MCP2515 is a CAN Bus to SPI adapter from Microchip Technology,
17 # as used in the Goodthopter series of boards. It requires a separate
18 # chip for voltage level conversion, such as the MCP2551.
20 import sys, time, string, cStringIO, struct, glob, os;
22 from GoodFETSPI import GoodFETSPI;
24 class GoodFETMCPCAN(GoodFETSPI):
25 """This class uses the regular SPI app to implement a CAN Bus
26 adapter on the Goodthopter10 hardware."""
27 MCPMODES=["Normal","Sleep","Loopback","Listen-only","Configuration",
28 "UNKNOWN","UNKNOWN","PowerUp"];
31 """Sets up the ports."""
33 self.MCPreset(); #Reset the chip.
34 # We're going to set some registers, so we must be in config
36 self.MCPreqstatConfiguration();
38 # If we don't enable promiscous mode, we'll miss a lot of
39 # packets. It can be manually disabled later.
40 #self.poke8(0x60,0xFF); #TODO Does this have any unpleasant side effects?
41 self.poke8(0x60,0x66); #Wanted FF, but some bits are reserved.
43 #Array of supported rates.
44 MCPrates=[10.4, 41.6, 83.3, 100, 125, 250, 500, 1000];
47 """Reset the MCP2515 chip."""
48 self.SPItrans([0xC0]);
51 ################ SETTING BAUD RATE ################
54 def MCPsetrate(self,rate=125):
55 """Sets the data rate in kHz."""
56 # Now we need to set the timing registers. See chapter 5 of
57 # the MCP2515 datasheet to get some clue as to how this
58 # arithmetic of this works.
61 #STORE the prior status
62 oldstatus=self.MCPcanstatint();
63 print "Setting rate of %i kHz." % rate;
64 #print "Current state is %s." % self.MCPcanstatstr();
65 self.MCPreqstatConfiguration();
66 # print "Switched to %s state." % self.MCPcanstatstr();
69 if rate>41 and rate<42:
70 # NOT CHECKED: based on kvaser website.
71 # Sets baud rate for 41.6 kbps
75 elif rate>10 and rate<11:
76 # NOT CHECKED: based on kvaser website.
77 # Sets baud rate for 10.4 kbps
82 #125 kHz, 16 TQ, not quite as worked out above.
91 elif rate>83 and rate<83.5:
93 # 0.04% error from 83.30
112 print "WARNING: Because of chip errata, this probably won't work."
114 print "Given unsupported rate of %i kHz." % rate;
115 print "Defaulting to 125kHz.";
119 self.poke8(0x2a,CNF1);
120 self.poke8(0x29,CNF2);
121 self.poke8(0x28,CNF3);
123 # and now return to whatever state we were in before
124 self.MCPreqstat(oldstatus);
125 #print "Reverted to %s." % self.MCPcanstatstr();
128 ################# STATE MANAGEMENT ##################
130 def MCPcanstat(self):
131 """Get the CAN Status."""
132 return self.peek8(0x0E);
133 def MCPcanstatstr(self):
134 """Read the present status as a string."""
135 opmod=self.MCPcanstatint();
136 return self.MCPMODES[opmod];
137 def MCPcanstatint(self):
138 """Read present status as an int."""
139 return self.MCPcanstat()>>5;
142 def MCPreqstat(self, state):
143 """Set the CAN state."""
145 self.MCPreqstatNormal();
147 self.MCPreqstatSleep();
149 self.MCPreqstatLoopback();
151 self.MCPreqstatListenOnly();
153 self.MCPreqstatConfiguration();
155 print "Invalid state entered; defaulting to Listen-Only"
156 self.MCPreqstatListenOnly();
157 def MCPreqstatNormal(self):
158 """Set the CAN state."""
160 self.MCPbitmodify(0x0F,0xE0,(state<<5));
161 def MCPreqstatSleep(self):
162 """Set the CAN state."""
164 self.MCPbitmodify(0x0F,0xE0,(state<<5));
165 def MCPreqstatLoopback(self):
166 """Set the CAN state."""
168 self.MCPbitmodify(0x0F,0xE0,(state<<5));
169 def MCPreqstatListenOnly(self):
170 """Set the CAN state."""
172 self.MCPbitmodify(0x0F,0xE0,(state<<5));
173 def MCPreqstatConfiguration(self):
174 """Set the CAN state."""
176 self.MCPbitmodify(0x0F,0xE0,(state<<5));
178 #################### RX MANAGEMENT #####################
180 def MCPrxstatus(self):
181 """Reads the RX Status by the SPI verb of the same name."""
182 data=self.SPItrans([0xB0,0x00]);
185 def MCPreadstatus(self):
186 """Reads the Read Status by the SPI verb of the same name."""
187 #See page 69 of the datasheet for the flag names.
188 data=self.SPItrans([0xA0,0x00]);
191 def readrxbuffer(self,packbuf=0):
192 """Reads the RX buffer. Might have old data."""
193 data=self.SPItrans([0x90|(packbuf<<2),
197 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00
201 return data[1:len(data)];
203 def fastrxpacket(self):
204 return self.readrxbuffer(0);
207 """Reads the next incoming packet from either buffer.
208 Returns None immediately if no packet is waiting."""
209 status=self.MCPrxstatus()&0xC0;
211 #Buffer 0 has higher priority.
212 return self.readrxbuffer(0);
214 #Buffer 1 has lower priority.
215 return self.readrxbuffer(1);
219 ################# TX MANAGEMENT ##################
221 def MCPrts(self,TXB0=False,TXB1=False,TXB2=False):
222 """Requests to send one of the transmit buffers."""
224 if TXB0: flags=flags|1;
225 if TXB1: flags=flags|2;
226 if TXB2: flags=flags|4;
229 print "Warning: Requesting to send no buffer.";
230 self.SPItrans([0x80|flags]);
232 def writetxbuffer(self,packet,packbuf=0):
233 """Writes the transmit buffer."""
235 self.SPItrans([0x40|(packbuf<<1)]+packet);
238 def txpacket(self,packet):
239 """Transmits a packet through one of the outbound buffers.
240 As usual, the packet should begin with SIDH.
241 For now, only TXB0 is supported."""
243 self.writetxbuffer(packet,0);
244 self.MCPrts(TXB0=True);
247 ############### UTILITY FUNCTIONS #################
249 def simpleParse(self,packet):
251 This will print a simple parsing of the data with the standard Id and the extended id parsed.
253 dataPt = ord(packet[0]);
254 dataPt2 = ord(packet[1]);
255 # check if we have a standard frame, the msb of the second
256 # nibble will be 1. otherwise it is an extended rame
257 stdCheck = dataPt2 & 0x0f
258 if( stdCheck == 16 ):
259 #arb id is first byte + 3 msb of the 2nd byte
260 dataPt = dataPt<<3 | dataPt2>>5
261 print "Standard Packet \n Arb ID: "+("%d"%dataPt)
263 #arb id is first byte + 3 msb + 2 lsb of 2nd byte +
264 # 3rd byte + 4th byte
265 dataPt = dataPt<<3 | dataPt2>>5
266 dataPt = dataPt<<2 | (dataPt2 & 0x03)
267 dataPt = dataPt<<8 | ord(packet[2])
268 dataPt = dataPt<<8 | ord(packet[3])
269 print "Extended Data Frame \n Arb ID: "+("%d"%dataPt)
273 dataLength = dataPt5 & 0x0e
274 #print "Data Length: "+("%d"%dataLength)
275 # Print the data packet
277 # Temporary, until correct packets are read
278 if( dataLength > 8 ):
280 toprint = self.pcket2str(packet[5:12])
282 # For reading correct packets
283 # if (dataLength > 8 ):
284 # print "Acceptable Length Exceeded"
285 # Data length value should never exceed 8
287 # toprint = self.pcket2str(packet[5:(5+dataLength)])
291 def packet2str(self,packet):
292 """Converts a packet from the internal format to a string."""
295 toprint=toprint+("%02x "%ord(bar))
300 def packet2parsed(self,data):
302 This method will parse the packet that was received via L{rxpacket}.
305 @param data: data packet read off of the MCP2515 from the CAN bus. format will be
306 14 bytes where each element is a character whose unicode integer value corresponds
307 to the hex value of the byte (use the ord() method).
310 @return: Dictionary of the packet parsed into various components. The key values will be as follows
312 1. ide : 1 if the message is an extended frame. 0 otherwise
313 2. eID : extended ID. Not included if not an extended frame
314 3. rtr : 1 if the message is a remote transmission request (RTR)
315 4. sID : Standard ID.
316 5. length: packet length (between 0 and 8)
317 6. db0 : Data byte 0 (not included if RTR message)
320 7. db7 : Data byte 7 (not included if RTR message)
327 #get the ide bit. allows us to check to see if we have an extended
329 packet['ide'] = (dp2 & 0x0f)>>3
330 #we have an extended frame
331 if( packet['ide'] != 0):
332 #get lower nibble, last 2 bits
334 eId = eId<<8 | ord(data[2])
335 eId = eId<<8 | ord(data[3])
337 packet['eID'] = " eID: %06d" %(eId)
338 packet['rtr'] = " rtr: %d" % (rtr)
341 packet['rtr'] = dp2>>4 & 0x01
344 # Create the standard ID. from the message
345 packet['sID'] = dp1<<3 | dp2>>5
346 packet['length'] = dp5 & 0x0f
348 #generate the data section
349 for i in range(0,packet['length']):
352 packet[dbidx] = ord(data[idx])
355 def packet2parsedstr(self,data):
357 This will return a string that is the parsed CAN message. The bytes will be parsed
358 for the standard ID, extended ID (if one is present), rtr, length and databytes (if present).
359 The message will be placed into a string as decimal integers not hex values. This method
360 calls L{packet2parsed} to do the packet parsing.
363 @param data: Data packet as returned by the L{rxpacket}
365 @return: String that shows the data message in decimal format, parsed.
367 packet = self.packet2parsed(data)
368 msg = "sID: %04d" %packet['sId']
369 if( packetParsed.get('eID')):
370 msg += " eID: %d" %packetParsed.get('eID')
371 msg += " rtr: %d"%packetParsed['rtr']
372 length = packetParsed['length']
373 msg += " length: %d"%length
375 for i in range(0,length):
377 msg +=" %03d"% ord(packetParsed[dbidx]) # could change this to HEX
378 #msg = self.client.packet2parsedstr(packet)
383 """Read a byte from the given address. Untested."""
384 data=self.SPItrans([0x03,adr&0xFF,00]);
386 def poke8(self,adr,val):
387 """Poke a value into RAM. Untested"""
388 self.SPItrans([0x02,adr&0xFF,val&0xFF]);
389 newval=self.peek8(adr);
391 print "Failed to poke %02x to %02x. Got %02x." % (adr,val,newval);
392 print "Are you not in idle mode?";
394 def MCPbitmodify(self,adr,mask,data):
395 """Writes a byte with a mask. Doesn't work for many registers."""
396 data=self.SPItrans([0x05,adr&0xFF,mask&0xFF,data&0xFF]);
399 ############### DEBUG UTILITIES: STATUS MESSAGES ##############
401 # def MCPrxstatusmessage(self):
402 # """Returns string indicating status of RX buffers"""
403 # status = self.MCPrxstatus();
406 # print "No RX message";
408 # print "Message in RXB0";
410 # print "Message in RXB1";
412 # print "Messages in both buffers";
418 # CNF3/2/1 = 0x28, 29, 2a