--- /dev/null
+#!/usr/bin/env python
+# GoodFET SPI Flash Client
+#
+# (C) 2012 Travis Goodspeed <travis at radiantmachines.com>
+#
+#
+# Ted's working copy
+# 1) getting hot reads on frequency
+# 2) allow sniffing in "normal" mode to get ack bits
+# --check if that's whats causing error flags in board-to-board transmission
+#
+#
+
+import sys;
+import binascii;
+import array;
+import csv, time, argparse;
+
+from GoodFETMCPCAN import GoodFETMCPCAN;
+from intelhex import IntelHex;
+
+class GoodFETMCPCANCommunication:
+
+ def __init__(self):
+ self.client=GoodFETMCPCAN();
+ self.client.serInit()
+ self.client.MCPsetup();
+
+
+ ##########################
+ # INFO
+ ##########################
+ #
+ # Prints MCP state info
+ #
+ def printInfo(self):
+ print "MCP2515 Info:\n\n";
+
+ print "Mode: %s" % self.client.MCPcanstatstr();
+ print "Read Status: %02x" % self.client.MCPreadstatus();
+ print "Rx Status: %02x" % self.client.MCPrxstatus();
+ print "Tx Errors: %3d" % self.client.peek8(0x1c);
+ print "Rx Errors: %3d\n" % self.client.peek8(0x1d);
+
+ print "Timing Info:";
+ print "CNF1: %02x" %self.client.peek8(0x2a);
+ print "CNF2: %02x" %self.client.peek8(0x29);
+ print "CNF3: %02x\n" %self.client.peek8(0x28);
+ print "RXB0 CTRL: %02x" %self.client.peek8(0x60);
+ print "RXB1 CTRL: %02x" %self.client.peek8(0x70);
+ print "RX Buffers:"
+ packet0=self.client.readrxbuffer(0);
+ packet1=self.client.readrxbuffer(1);
+ for foo in [packet0, packet1]:
+ print self.client.packet2str(foo);
+
+ def reset(self):
+ self.client.MCPsetup();
+
+ def sniff(self,freq,duration,filename,description, verbose=True, comment=None):
+ self.client.MCPsetrate(freq);
+ outfile = open(filename,'a');
+ dataWriter = csv.writer(outfile,delimiter=',');
+ dataWriter.writerow(['# Time Error Bytes 1-13']);
+ dataWriter.writerow(['#' + description])
+
+ self.client.MCPreqstatListenOnly();
+ print "Listening...";
+ packetcount = 0;
+ starttime = time.time();
+
+ while((time.time()-starttime < duration)):
+ packet=self.client.rxpacket();
+ if packet!=None:
+ if( verbose==True):
+ print self.client.packet2str(packet)
+ packetcount+=1;
+ row = [];
+ row.append("%f"%time.time());
+ if (self.client.peek8(0x2C) & 0x80):
+ self.client.MCPbitmodify(0x2C,0x80,0x00);
+ print "ERROR: Malformed packet recieved: " + self.client.packet2str(packet);
+ row.append(1);
+ else:
+ row.append(0);
+
+ #write comment
+ row.append(comment)
+ for byte in packet:
+ row.append("%02x"%ord(byte));
+ dataWriter.writerow(row);
+
+ outfile.close()
+ print "Listened for %x seconds, captured %x packets." %(duration,packetcount);
+
+
+
+ def sniffTest(self, freq):
+ self.client.MCPsetup();
+
+ rate = freq;
+
+ print "Calling MCPsetrate for %i." %rate;
+ self.client.MCPsetrate(rate);
+ self.client.MCPreqstatNormal();
+
+ print "Mode: %s" % self.client.MCPcanstatstr();
+ print "CNF1: %02x" %self.client.peek8(0x2a);
+ print "CNF2: %02x" %self.client.peek8(0x29);
+ print "CNF3: %02x\n" %self.client.peek8(0x28);
+
+ while(1):
+ packet=self.client.rxpacket();
+
+ if packet!=None:
+ if (self.client.peek8(0x2C) & 0x80):
+ self.client.MCPbitmodify(0x2C,0x80,0x00);
+ print "malformed packet recieved: "+ self.client.packet2str(packet);
+ else:
+ print "properly formatted packet recieved" + self.client.packet2str(packet);
+
+
+ def freqtest(self,freq):
+ self.client.MCPsetup();
+
+ self.client.MCPsetrate(freq);
+ self.client.MCPreqstatListenOnly();
+
+ print "CAN Freq Test: %3d kHz" %freq;
+
+ x = 0;
+ errors = 0;
+
+ starttime = time.time();
+ while((time.time()-starttime < args.time)):
+ packet=self.client.rxpacket();
+ if packet!=None:
+ x+=1;
+
+ if (self.client.peek8(0x2C) & 0x80):
+ print "malformed packet recieved"
+ errors+=1;
+ self.client.MCPbitmodify(0x2C,0x80,0x00);
+ else:
+ print self.client.packet2str(packet);
+
+ print "Results for %3.1d kHz: recieved %3d packets, registered %3d RX errors." %(freq, x, errors);
+
+
+ def isniff(self,freq):
+ """ An intelligent sniffer, decodes message format """
+ """ More features to be added soon """
+
+ self.client.MCPsetrate(freq);
+ self.client.MCPreqstatListenOnly();
+ while 1:
+ packet=self.client.rxpacket();
+ if packet!=None:
+ plist=[];
+ for byte in packet:
+ plist.append(byte);
+ arbid=plist[0:2];
+ eid=plist[2:4];
+ dlc=plist[4:5];
+ data=plist[5:13];
+ print "\nArbID: " + self.client.packet2str(arbid);
+ print "EID: " + self.client.packet2str(eid);
+ print "DLC: " + self.client.packet2str(dlc);
+ print "Data: " + self.client.packet2str(data);
+
+ def test(self):
+ print "\nMCP2515 Self Test:";
+
+ #Switch to config mode and try to rewrite TEC.
+ self.client.MCPreqstatConfiguration();
+ self.client.poke8(0x00,0xde);
+ if self.client.peek8(0x00)!=0xde:
+ print "ERROR: Poke to TEC failed.";
+ else:
+ print "SUCCESS: Register read/write.";
+
+ #Switch to Loopback mode and try to catch our own packet.
+ self.client.MCPreqstatLoopback();
+
+ packet1 = [0x00,
+ 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID
+ 0x00, 0x00,
+ 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME
+ # LOWER nibble is DLC
+ 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF]
+ self.client.txpacket(packet1);
+ self.client.txpacket(packet1);
+ print "Waiting on loopback packets.";
+ packet=None;
+ while(1):
+ packet=self.client.rxpacket();
+ if packet!=None:
+ print "Message recieved: %s" % self.client.packet2str(packet);
+ break;
+
+
+ def spit(self,freq):
+ self.client.MCPsetrate(freq);
+ self.client.MCPreqstatNormal();
+
+ print "Tx Errors: %3d" % self.client.peek8(0x1c);
+ print "Rx Errors: %3d" % self.client.peek8(0x1d);
+ print "Error Flags: %02x\n" % self.client.peek8(0x2d);
+ print "TXB0CTRL: %02x" %self.client.peek8(0x30);
+ print "CANINTF: %02x" %self.client.peek8(0x2C);
+
+
+ packet = [0x00,
+ 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID
+ 0x00, 0x00,
+ 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME
+ # LOWER nibble is DLC
+ 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF]
+
+ self.client.txpacket(packet);
+
+ if(self.client.peek8(0x2C)&0x80)==0x80:
+ print "Error flag raised on transmission. Clearing this flag and proceeding.\n"
+ print "INT Flags: %02x" % self.client.peek8(0x2c);
+ self.client.MCPbitmodify(0x2C,0x80,0x00);
+ print "INT Flags modified to: %02x\n" % self.client.peek8(0x2c);
+ print "TXB0CTRL: %02x" %self.client.peek8(0x30);
+ self.client.MCPbitmodify(0x30,0x08,0x00);
+ print "TXB0CTRL modified to: %02x\n" %self.client.peek8(0x30);
+
+ print "message sending attempted.";
+ print "Tx Errors: %02x" % self.client.peek8(0x1c);
+ print "Rx Errors: %02x" % self.client.peek8(0x1d);
+ print "Error Flags: %02x" % self.client.peek8(0x2d);
+
+
+
+if __name__ == "__main__":
+
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description='''\
+
+ Run commands on the MCP2515. Valid commands are:
+
+ info
+ test
+ peek 0x(start) [0x(stop)]
+ reset
+
+ sniff
+ freqtest
+ snifftest
+ spit
+ ''')
+
+
+ parser.add_argument('verb', choices=['info', 'test','peek', 'reset', 'sniff', 'freqtest','snifftest', 'spit']);
+ parser.add_argument('-f', '--freq', type=int, default=500, help='The desired frequency (kHz)', choices=[100, 125, 250, 500, 1000]);
+ parser.add_argument('-t','--time', type=int, default=15, help='The duration to run the command (s)');
+ parser.add_argument('-o', '--output', default="../../contrib/ted/sniff_out.csv",help='Output file');
+ parser.add_argument("-d", "--description", help='Description of experiment (included in the output file)', default="");
+ parser.add_argument('-v',"--verbose",action='store_false',help='-v will stop packet output to terminal', default=True);
+ parser.add_argument('-c','--comment', help='Comment attached to ech packet uploaded',default=None);
+
+ args = parser.parse_args();
+ freq = args.freq
+ duration = args.time
+ filename = args.output
+ description = args.description
+ verbose = args.verbose
+ comments = args.comment
+
+ comm = GoodFETMCPCANCommunication();
+
+ ##########################
+ # INFO
+ ##########################
+ #
+ # Prints MCP state info
+ #
+ if(args.verb=="info"):
+ comm.printInfo()
+
+
+ ##########################
+ # RESET
+ ##########################
+ #
+ #
+
+ if(args.verb=="reset"):
+ comm.reset()
+
+ ##########################
+ # SNIFF
+ ##########################
+ #
+ # runs in ListenOnly mode
+ # utility function to pull info off the car's CAN bus
+ #
+
+ if(args.verb=="sniff"):
+ comm.sniff(freq=freq,duration=duration,filename=filename,description=description,verbose=verbose,comment=comments)
+
+
+
+ ##########################
+ # SNIFF TEST
+ ##########################
+ #
+ # runs in NORMAL mode
+ # intended for NETWORKED MCP chips to verify proper operation
+ #
+
+ if(args.verb=="snifftest"):
+ comm.sniffTest(freq=freq)
+
+ ##########################
+ # FREQ TEST
+ ##########################
+ #
+ # runs in LISTEN ONLY mode
+ # tests bus for desired frequency --> sniffs bus for specified length of time and reports
+ # if packets were properly formatted
+ #
+ #
+
+ if(args.verb=="freqtest"):
+ comm.freqtest(freq=freq)
+
+ ##########################
+ # iSniff
+ ##########################
+ #
+ # """ An intelligent sniffer, decodes message format """
+ # """ More features to be added soon """
+ if(args.verb=="isniff"):
+ comm.isniff(freq=freq)
+
+
+ ##########################
+ # MCP TEST
+ ##########################
+ #
+ # Runs in LOOPBACK mode
+ # self-check diagnostic
+ # wasn't working before due to improperly formatted packet
+ #
+ # ...add automatic packet check rather than making user verify successful packet
+ if(args.verb=="test"):
+ comm.test()
+
+
+ if(args.verb=="peek"):
+ start=0x0000;
+ if(len(sys.argv)>2):
+ start=int(sys.argv[2],16);
+ stop=start;
+ if(len(sys.argv)>3):
+ stop=int(sys.argv[3],16);
+ print "Peeking from %04x to %04x." % (start,stop);
+ while start<=stop:
+ print "%04x: %02x" % (start,client.peek8(start));
+ start=start+1;
+
+ ##########################
+ # SPIT
+ ##########################
+ #
+ # Basic packet transmission
+ # runs in NORMAL MODE!
+ #
+ # checking TX error flags--> currently throwing error flags on every
+ # transmission (travis thinks this is because we're sniffing in listen-only
+ # and thus not generating an ack bit on the recieving board)
+ if(args.verb=="spit"):
+ comm.spit(freq=freq)
+
+
+
+
+
+
+
+
+
+
print "\n%s sniff [kHz]" % sys.argv[0];
print "\n%s isniff [kHz]" % sys.argv[0];
+ print "\n%s spit [kHz]" % sys.argv[0];
+
print "\nSupported rates: 83.3, 100, 125, 250, 500, 1000 kHz.";
sys.exit();
print "Read Status: %02x" % client.MCPreadstatus();
print "Rx Status: %02x" % client.MCPrxstatus();
print "Tx Errors: %3d" % client.peek8(0x1c);
- print "Rx Errors: %3d" % client.peek8(0x1d);
+ print "Rx Errors: %3d\n" % client.peek8(0x1d);
+
+ print "Timing Info:";
+ print "CNF1: %02x" %client.peek8(0x2a);
+ print "CNF2: %02x" %client.peek8(0x29);
+ print "CNF3: %02x\n" %client.peek8(0x28);
+ print "RXB0 CTRL: %02x" %client.peek8(0x60);
+ print "RXB1 CTRL: %02x" %client.peek8(0x70);
print "RX Buffers:"
packet0=client.readrxbuffer(0);
packet1=client.readrxbuffer(1);
if(sys.argv[1]=="sniff"):
if len(sys.argv)>2:
rate=float(sys.argv[2]);
+ print "Calling MCPsetrate for %i." %rate;
client.MCPsetrate(rate);
client.MCPreqstatListenOnly();
- while 1:
+
+ print "Mode: %s" % client.MCPcanstatstr();
+
+ print "CNF1: %02x" %client.peek8(0x2a);
+ print "CNF2: %02x" %client.peek8(0x29);
+ print "CNF3: %02x\n" %client.peek8(0x28);
+
+ while(1):
packet=client.rxpacket();
if packet!=None:
print client.packet2str(packet);
+
+ if (client.peek8(0x2C) & 0x80):
+ client.MCPbitmodify(0x2C,0x80,0x00);
+ print"...malformed packet recieved";
+
+if(sys.argv[1]=="snifftest"):
+
+ freqrange=[10.4, 41.6, 83.3, 100, 125, 250, 500, 1000];
+
+ for rate in freqrange:
+
+ print "CAN Freq Test: %3d kHz" %rate;
+ client.MCPsetrate(rate);
+ #print "CNF1/2/3: %02x %02x %02x" %(client.peek8(0x2a), client.peek8(0x29),client.peek8(0x28));
+ client.MCPreqstatListenOnly();
+ print "Mode: %s" % client.MCPcanstatstr();
+ x = 0;
+ errors = 0;
+
+ for n in range(0,400):
+ packet=client.rxpacket();
+ if packet!=None:
+ print client.packet2str(packet);
+ x+=1;
+
+ if (client.peek8(0x2C) & 0x80):
+ errors+=1;
+ client.MCPbitmodify(0x2C,0x80,0x00);
+
+ if x==0:
+ print "No packets sniffed for %3d kHz" %rate;
+ else:
+ percenterror = float(errors/x);
+
+ print "Results for %3.1 kHz: recieved %3d packets, registered %3d RX errors, for a %3.3f percent error rate." %(rate, x, errors, percenterrors);
+
+ client.MCPreset();
if(sys.argv[1]=="isniff"):
""" An intelligent sniffer, decodes message format """
print "Data: " + client.packet2str(data);
if(sys.argv[1]=="test"):
- print "MCP2515 Self Test:";
+ print "\nMCP2515 Self Test:";
#Switch to config mode and try to rewrite TEC.
client.MCPreqstatConfiguration();
#Switch to Loopback mode and try to catch our own packet.
client.MCPreqstatLoopback();
- client.txpacket([0xb1, 0x6b, 0x00, 0x65,
- 0xb1, 0x6b, 0x00, 0x65
- ]);
- print "Waiting on loopback packet.";
+
+ packet1 = [0x00,
+ 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID
+ 0x00, 0x00,
+ 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME
+ # LOWER nibble is DLC
+ 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF]
+ client.txpacket(packet1);
+ client.txpacket(packet1);
+ print "Waiting on loopback packets.";
packet=None;
- while packet==None:
+ while(1):
packet=client.rxpacket();
- print "Success! Got %s" % client.packet2str(packet);
+ if packet!=None:
+ print "Message recieved: %s" % client.packet2str(packet);
+
+
+
if(sys.argv[1]=="peek"):
start=0x0000;
if(len(sys.argv)>2):
while start<=stop:
print "%04x: %02x" % (start,client.peek8(start));
start=start+1;
+
+# AWWW YEAAAA CODIN THAT SHIT
+# as written, this should
+
+if(sys.argv[1]=="spit"):
+
+ if len(sys.argv)>2:
+ rate=float(sys.argv[2]);
+ print "Calling MCPsetrate for %i." %rate;
+ client.MCPsetrate(rate);
+
+ client.MCPreqstatNormal();
+
+ packet = [0x00,
+ 0x08, # LOWER nibble must be 8 or greater to set EXTENDED ID
+ 0x00, 0x00,
+ 0x08, # UPPER nibble must be 0 to set RTR bit for DATA FRAME
+ # LOWER nibble is DLC
+ 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF]
+
+ client.txpacket(packet);
+ data = client.peek8(0x30);
+ while (data&0x08)==0:
+ print "waiting...";
+ data=client.peek8(0x30);
+ print "message successfully sent!";
+
+if(sys.argv[1]=="setbitrate"):
+ if len(sys.argv)>2:
+ rate=float(sys.argv[2]);
+ print "Calling MCPsetrate for %i." %rate;
+ client.MCPsetrate(rate);
+
+
+
+
+
+