2 # GoodFET SPI Flash Client
4 # (C) 2012 Travis Goodspeed <travis at radiantmachines.com>
8 # 1) getting hot reads on frequency
9 # 2) allow sniffing in "normal" mode to get ack bits
10 # --check if that's whats causing error flags in board-to-board transmission
17 import csv, time, argparse;
20 from random import randrange
21 from GoodFETMCPCAN import GoodFETMCPCAN;
22 from intelhex import IntelHex;
25 class GoodFETMCPCANCommunication:
27 def __init__(self, dataLocation):
28 self.client=GoodFETMCPCAN();
29 """ Communication with the bus"""
31 self.client.MCPsetup();
32 #self.DATA_LOCATION = "../../contrib/ThayerData/"
33 self.DATA_LOCATION = dataLocation;
34 """ Stores file data location. This is the root folder where basic sniffs will be stored"""
35 self.INJECT_DATA_LOCATION = self.DATA_LOCATION+"InjectedData/"
36 """ stores the sub folder path where injected data will be stored"""
42 This method will print information about the board to the terminal.
43 It is good for diagnostics
46 self.client.MCPreqstatConfiguration();
48 print "MCP2515 Info:\n\n";
50 print "Mode: %s" % self.client.MCPcanstatstr();
51 print "Read Status: %02x" % self.client.MCPreadstatus();
52 print "Rx Status: %02x" % self.client.MCPrxstatus();
53 print "Error Flags: %02x" % self.client.peek8(0x2D);
54 print "Tx Errors: %3d" % self.client.peek8(0x1c);
55 print "Rx Errors: %3d\n" % self.client.peek8(0x1d);
58 print "CNF1: %02x" %self.client.peek8(0x2a);
59 print "CNF2: %02x" %self.client.peek8(0x29);
60 print "CNF3: %02x\n" %self.client.peek8(0x28);
61 print "RXB0 CTRL: %02x" %self.client.peek8(0x60);
62 print "RXB1 CTRL: %02x" %self.client.peek8(0x70);
65 print "RXB0: %02x" %self.client.peek8(0x60);
66 print "RXB1: %02x" %self.client.peek8(0x70);
67 print "RXB0 masks: %02x, %02x, %02x, %02x" %(self.client.peek8(0x20), self.client.peek8(0x21), self.client.peek8(0x22), self.client.peek8(0x23));
68 print "RXB1 masks: %02x, %02x, %02x, %02x" %(self.client.peek8(0x24), self.client.peek8(0x25), self.client.peek8(0x26), self.client.peek8(0x27));
72 packet0=self.client.readrxbuffer(0);
73 packet1=self.client.readrxbuffer(1);
74 for foo in [packet0, packet1]:
75 print self.client.packet2str(foo);
81 self.client.MCPsetup();
84 ##########################
86 ##########################
88 def sniff(self,freq,duration,description, verbose=True, comment=None, filename=None, standardid=None, debug=False, faster=False, parsed=True, data = None,writeToFile=True, db0 = None, db1 = None):
92 #reset eveything on the chip
96 # filtering for specific packets
97 if(db0 != None and db1 != None and standardid != None):
98 self.filterForPacket(standardid[0], db0, db1, verbose)
101 comment += ("f%d[%d][%d]" %(standardid[0], db0, db1))
102 # filtering for standard ID
103 elif(standardid != None):
104 self.addFilter(standardid, verbose)
107 for ID in standardid:
108 comment += ("f%d" %(ID))
111 self.client.MCPsetrate(freq);
113 # This will handle the files so that we do not loose them. each day we will create a new csv file
114 if( filename==None and writeToFile == True):
115 #get folder information (based on today's date)
116 now = datetime.datetime.now()
117 datestr = now.strftime("%Y%m%d")
118 path = self.DATA_LOCATION+datestr+".csv"
121 if( writeToFile == True):
122 outfile = open(filename,'a');
123 dataWriter = csv.writer(outfile,delimiter=',');
124 dataWriter.writerow(['# Time Error Bytes 1-13']);
125 dataWriter.writerow(['#' + description])
127 self.client.MCPreqstatNormal();
128 print "Listening...";
130 starttime = time.time();
132 while((time.time()-starttime < duration)):
135 packet=self.client.fastrxpacket();
137 packet=self.client.rxpacket();
139 #add the data to list if the pointer was included
140 if(data != None and packet != None):
141 #data.append(self.client.packet2parsedstr(packet))
142 packetParsed = self.client.packet2parsed(packet)
143 packetParsed["time"] =time.time()
144 data.put(packetParsed)
147 MCPstatusReg = self.client.MCPrxstatus();
148 messagestat=MCPstatusReg&0xC0;
149 messagetype=MCPstatusReg&0x18;
150 if(messagestat == 0xC0):
151 print "Message in both buffers; message type is %02x (0x00 is standard data, 0x08 is standard remote)." %messagetype
152 elif(messagestat == 0x80):
153 print "Message in RXB1; message type is %02x (0x00 is standard data, 0x08 is standard remote)." %messagetype
154 elif(messagestat == 0x40):
155 print "Message in RXB0; message type is %02x (0x00 is standard data, 0x08 is standard remote)." %messagetype
156 elif(messagestat == 0x00):
157 print "No messages in buffers."
158 #check to see if there was a packet
161 if (packet!=None and writeToFile == True):
164 row.append("%f"%time.time());
167 #if we want to print a parsed message
169 packetParsed = self.client.packet2parsed(packet)
170 sId = packetParsed.get('sID')
171 msg = "sID: %04d" %sId
172 if( packetParsed.get('eID')):
173 msg += " eID: %d" %packetParsed.get('eID')
174 msg += " rtr: %d"%packetParsed['rtr']
175 length = packetParsed['length']
176 msg += " length: %d"%length
178 for i in range(0,length):
180 msg +=" %03d"% packetParsed[dbidx]
181 #msg = self.client.packet2parsedstr(packet)
183 # if we want to print just the message as it is read off the chip
185 print self.client.packet2str(packet)
190 MCPeflgReg=self.client.peek8(0x2D);
191 print"EFLG register equals: %x" %MCPeflgReg;
192 if((MCPeflgReg & 0xC0)==0xC0):
193 print "WARNING: BOTH overflow flags set. Missed a packet. Clearing and proceeding."
194 elif(MCPeflgReg & 0x80):
195 print "WARNING: RXB1 overflow flag set. A packet has been missed. Clearing and proceeding."
196 elif(MCPeflgReg & 0x40):
197 print "WARNING: RXB0 overflow flag set. A packet has been missed. Clearing and proceeding."
198 self.client.MCPbitmodify(0x2D,0xC0,0x00);
199 print"EFLG register set to: %x" % self.client.peek(0x2D);
202 if (self.client.peek8(0x2C) & 0x80):
203 self.client.MCPbitmodify(0x2C,0x80,0x00);
204 print "ERROR: Malformed packet recieved: " + self.client.packet2str(packet);
209 row.append(0); #since we don't check for errors if we're not in debug mode...
212 #how long the sniff was for
214 #boolean that tells us if there was filtering. 0 == no filters, 1 == filters
215 if(standardid != None):
219 #write packet to file
221 row.append("%02x"%ord(byte));
222 dataWriter.writerow(row);
223 if(writeToFile == True):
225 print "Listened for %d seconds, captured %d packets." %(duration,packetcount);
229 # def filterStdSweep(self, freq, low, high, time = 5):
231 # self.client.serInit()
232 # self.client.MCPsetup()
233 # for i in range(low, high+1, 6):
234 # print "sniffing id: %d, %d, %d, %d, %d, %d" % (i,i+1,i+2,i+3,i+4,i+5)
235 # comment= "sweepFilter: "
236 # #comment = "sweepFilter_%d_%d_%d_%d_%d_%d" % (i,i+1,i+2,i+3,i+4,i+5)
237 # description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d, %d, %d, %d, %d, %d" % (i,i+1,i+2,i+3,i+4,i+5)
238 # count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [i, i+1, i+2, i+3, i+4, i+5])
240 # for j in range(i,i+5):
241 # comment = "sweepFilter: "
242 # #comment = "sweepFilter: %d" % (j)
243 # description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d " % j
244 # count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [j, j, j, j])
249 # def sweepRandom(self, freq, number = 5, time = 200):
252 # self.client.serInit()
253 # self.client.MCPsetup()
254 # for i in range(0,number+1,6):
256 # comment = "sweepFilter: "
257 # for j in range(0,6,1):
258 # id = randrange(2047)
259 # #comment += "_%d" % id
263 # description = "Running a sweep filer for all the possible standard IDs. This runs the following : " + comment
264 # count = self.sniff(freq=freq, duration=time, description=description, comment = comment, standardid = idsTemp)
266 # for element in idsTemp:
267 # #comment = "sweepFilter: %d" % (element)
268 # comment="sweepFilter: "
269 # description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d " % element
270 # count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [element, element, element])
275 def sniffTest(self, freq):
277 This method will preform a test to see if we can sniff corretly formed packets from the CAN bus.
280 @param freq: frequency of the CAN bus
284 print "Calling MCPsetrate for %i." %rate;
285 self.client.MCPsetrate(rate);
286 self.client.MCPreqstatNormal();
288 print "Mode: %s" % self.client.MCPcanstatstr();
289 print "CNF1: %02x" %self.client.peek8(0x2a);
290 print "CNF2: %02x" %self.client.peek8(0x29);
291 print "CNF3: %02x\n" %self.client.peek8(0x28);
294 packet=self.client.rxpacket();
297 if (self.client.peek8(0x2C) & 0x80):
298 self.client.MCPbitmodify(0x2C,0x80,0x00);
299 print "malformed packet recieved: "+ self.client.packet2str(packet);
301 print "properly formatted packet recieved" + self.client.packet2str(packet);
304 def freqtest(self,freq):
306 This method will test the frequency provided to see if it is the correct frequency for this CAN bus.
309 @param freq: The frequency to listen to the CAN bus.
312 self.client.MCPsetup();
314 self.client.MCPsetrate(freq);
315 self.client.MCPreqstatListenOnly();
317 print "CAN Freq Test: %3d kHz" %freq;
322 starttime = time.time();
323 while((time.time()-starttime < args.time)):
324 packet=self.client.rxpacket();
328 if (self.client.peek8(0x2C) & 0x80):
329 print "malformed packet recieved"
331 self.client.MCPbitmodify(0x2C,0x80,0x00);
333 print self.client.packet2str(packet);
335 print "Results for %3.1d kHz: recieved %3d packets, registered %3d RX errors." %(freq, x, errors);
338 def isniff(self,freq):
339 """ An intelligent sniffer, decodes message format """
340 """ More features to be added soon """
342 self.client.MCPsetrate(freq);
343 self.client.MCPreqstatListenOnly();
345 packet=self.client.rxpacket();
354 print "\nArbID: " + self.client.packet2str(arbid);
355 print "EID: " + self.client.packet2str(eid);
356 print "DLC: " + self.client.packet2str(dlc);
357 print "Data: " + self.client.packet2str(data);
360 """ This will perform a test on the GOODTHOPTER10. Diagnostic messages will be printed
364 print "Just reset..."
365 print "EFLG register: %02x" % self.client.peek8(0x2d);
366 print "Tx Errors: %3d" % self.client.peek8(0x1c);
367 print "Rx Errors: %3d" % self.client.peek8(0x1d);
368 print "CANINTF: %02x" %self.client.peek8(0x2C);
369 self.client.MCPreqstatConfiguration();
370 self.client.poke8(0x60,0x66);
371 self.client.MCPsetrate(500);
372 self.client.MCPreqstatNormal();
373 print "In normal mode now"
374 print "EFLG register: %02x" % self.client.peek8(0x2d);
375 print "Tx Errors: %3d" % self.client.peek8(0x1c);
376 print "Rx Errors: %3d" % self.client.peek8(0x1d);
377 print "CANINTF: %02x" %self.client.peek8(0x2C);
378 print "Waiting on packets.";
382 packet=self.client.rxpacket();
384 print "Message recieved: %s" % self.client.packet2str(packet);
386 checkcount=checkcount+1;
387 if (checkcount%30==0):
388 print "EFLG register: %02x" % self.client.peek8(0x2d);
389 print "Tx Errors: %3d" % self.client.peek8(0x1c);
390 print "Rx Errors: %3d" % self.client.peek8(0x1d);
391 print "CANINTF: %02x" %self.client.peek8(0x2C);
396 def addFilter(self,standardid, verbose= True):
397 """ This method will configure filters on the board. Filters are positive filters meaning that they will only
398 store messages that match the ids provided in the list of standardid. Since there are 2 buffers and due to the configuration
399 of how the filtering works (see MCP2515 documentation), at least 3 filters must be set to guarentee you do not get any
400 unwanted messages. However even with only 1 filter set you should get all messages from that ID but the other buffer will store
401 any additional messages.
402 @type standardid: list of integers
403 @param standardid: List of standard ids that need to be set. There can be at most 6 filters set.
404 @type verbose: Boolean
405 @param verbose: If true it will print out messages and diagnostics to terminal.
408 @return: This method does not return anything
409 @todo: rename setFilters
412 ### ON-CHIP FILTERING
413 if(standardid != None):
414 self.client.MCPreqstatConfiguration();
415 self.client.poke8(0x60,0x26); # set RXB0 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RMX0=1, BUKT=1)
416 self.client.poke8(0x20,0xFF); #set buffer 0 mask 1 (SID 10:3) to FF
417 self.client.poke8(0x21,0xE0); #set buffer 0 mask 2 bits 7:5 (SID 2:0) to 1s
418 if(len(standardid)>2):
419 self.client.poke8(0x70,0x20); # set RXB1 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RMX0=1)
420 self.client.poke8(0x24,0xFF); #set buffer 1 mask 1 (SID 10:3) to FF
421 self.client.poke8(0x25,0xE0); #set buffer 1 mask 2 bits 7:5 (SID 2:0) to 1s
423 for filter,ID in enumerate(standardid):
444 #### split SID into different regs
445 SIDlow = (ID & 0x07) << 5; # get SID bits 2:0, rotate them to bits 7:5
446 SIDhigh = (ID >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
449 self.client.poke8(RXFSIDH,SIDhigh);
450 self.client.poke8(RXFSIDL, SIDlow);
452 if (verbose == True):
453 print "Filtering for SID %d (0x%02xh) with filter #%d"%(ID, ID, filter);
455 self.client.MCPreqstatNormal();
457 def filterForPacket(self, standardid, DB0, DB1, verbose= True):
459 This method will configure filters on the board to listen for a specific packet originating
460 from standardid with data bytes 0 and 1. It will configure all six filters, so you will not receive any other packets.
462 @type standardid: integer
463 @param standardid: standardID to listen for
465 @param standardid: DB0 contents to filter for
467 @param standardid: DB1 contents to filter for
468 @type verbose: Boolean
469 @param verbose: If true it will print out messages and diagnostics to terminal.
472 @return: This method does not return anything
475 ### ON-CHIP FILTERING
477 self.client.MCPreqstatConfiguration();
479 # SID filtering: set CTRL registers to only accept standard messages
480 self.client.poke8(0x60,0x06); # set RXB0 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RXM=1, BUKT=1)
481 self.client.poke8(0x70,0x00); # set RXB1 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RXM0=1)
483 # Mask buffer 0 to match SID, DB0, DB1
484 self.client.poke8(0x20,0xFF); #set buffer 0 mask 1 (SID 10:3) to FF
485 self.client.poke8(0x21,0xE0); #set buffer 0 mask 2 bits 7:5 (SID 2:0) to 1s
486 self.client.poke8(0x22,0xFF); #set buffer 0 mask 3 (DB0) to FF
487 self.client.poke8(0x23,0xFF); #set buffer 0 mask 4 (DB0) to FF
489 # Mask buffer 1 to match SID, DB0, DB1
490 self.client.poke8(0x24,0xFF); #set buffer 1 mask 1 (SID 10:3) to FF
491 self.client.poke8(0x25,0xE0); #set buffer 1 mask 2 bits 7:5 (SID 2:0) to 1s
492 self.client.poke8(0x26,0xFF); #set buffer 1 mask 3 (DB0) to FF
493 self.client.poke8(0x27,0xFF); #set buffer 1 mask 4 (DB1) to FF
495 # Split SID into high and low bytes
496 SIDlow = (standardid & 0x07) << 5; # get SID bits 2:0, rotate them to bits 7:5
497 SIDhigh = (standardid >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
500 for filter in range(0,5):
533 self.client.poke8(RXFSIDH, SIDhigh);
534 self.client.poke8(RXFSIDL, SIDlow);
535 self.client.poke8(RXFDB0, DB0);
536 self.client.poke8(RXFDB1, DB1);
538 if (verbose == True):
539 print "Filtering for SID %d DB0 %d DB1 %d with filter #%d"%(standardid, DB0, DB1, filter);
541 self.client.MCPreqstatNormal();
544 def spitSetup(self,freq):
546 This method sets up the chip for transmitting messages, but does not transmit anything itself.
549 self.client.MCPsetrate(freq);
550 self.client.MCPreqstatNormal();
553 def spitSingle(self,freq, standardid, repeat,writes, period = None, debug = False, packet = None):
555 This method will spit a single message onto the bus. If there is no packet information provided then the
556 message will be sent as a remote transmission request (RTR). The packet length is assumed to be 8 bytes The message can be repeated given number of times with
557 a gap of period (milliseconds) between each message. This will continue for the the number of times specified in the writes input.
558 This method will setup the bus and call the spit method, L{spit}. This method includes a bus reset and initialization.
561 @param freq: The frequency of the bus
563 @type standardid: list of integer
564 @param standardid: This is a single length list with one integer elment that corresponds to the standard id you wish to write to
566 @type repeat: Boolean
567 @param repeat: If true the message will be repeatedly injected. if not the message will only be injected 1 time
569 @type writes: Integer
570 @param writes: Number of writes of the packet
572 @type period: Integer
573 @param period: Time delay between injections of the packet in Milliseconds
576 @param debug: When true debug status messages will be printed to the terminal
579 @param packet: Contains the data bytes for the packet which is assumed to be of length 8. Each byte is stored as
580 an integer and can range from 0 to 255 (8 bits). If packet == None then an RTR will be sent on the given
584 self.spitSetup(freq);
585 spit(self,freq, standardid, repeat,writes, period, debug , packet)
587 def spit(self,freq, standardid, repeat,writes, period = None, debug = False, packet = None):
589 This method will spit a single message onto the bus. If there is no packet information provided then the
590 message will be sent as a remote transmission request (RTR). The packet length is assumed to be 8 bytes The message can be repeated a given number of times with
591 a gap of period (milliseconds) between each message. This will continue for the the number of times specified in the writes input.
592 This method does not include bus setup, it must be done before the method call.
596 @param freq: The frequency of the bus
598 @type standardid: list of integer
599 @param standardid: This is a single length list with one integer elment that corresponds to the standard id you wish to write to
601 @type repeat: Boolean
602 @param repeat: If true the message will be repeatedly injected. if not the message will only be injected 1 time
604 @type writes: Integer
605 @param writes: Number of writes of the packet
607 @type period: Integer
608 @param period: Time delay between injections of the packet in Milliseconds
611 @param debug: When true debug status messages will be printed to the terminal
614 @param packet: Contains the data bytes for the packet which is assumed to be of length 8. Each byte is stored as
615 an integer and can range from 0 to 255 (8 bits). If packet == None then an RTR will be sent on the given
620 #### split SID into different regs
621 SIDlow = (standardid[0] & 0x07) << 5; # get SID bits 2:0, rotate them to bits 7:5
622 SIDhigh = (standardid[0] >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
626 # if no packet, RTR for inputted arbID
627 # so packet to transmit is SID + padding out EID registers + RTR request (set bit 6, clear lower nibble of DLC register)
628 packet = [SIDhigh, SIDlow, 0x00,0x00,0x40]
633 # if we do have a packet, packet is SID + padding out EID registers + DLC of 8 + packet
635 """@todo: allow for variable-length packets"""
636 # TODO: allow for variable-length packets
638 packet = [SIDhigh, SIDlow, 0x00,0x00, # pad out EID regs
639 0x08, # bit 6 must be set to 0 for data frame (1 for RTR)
640 # lower nibble is DLC
641 packet[0],packet[1],packet[2],packet[3],packet[4],packet[5],packet[6],packet[7]]
645 if self.client.MCPcanstat()>>5!=0:
646 print "Warning: currently in %s mode. NOT in normal mode! May not transmit.\n" %self.client.MCPcanstatstr();
647 print "\nInitial state:"
648 print "Tx Errors: %3d" % self.client.peek8(0x1c);
649 print "Rx Errors: %3d" % self.client.peek8(0x1d);
650 print "Error Flags: %02x\n" % self.client.peek8(0x2d);
651 print "TXB0CTRL: %02x" %self.client.peek8(0x30);
652 print "CANINTF: %02x\n" %self.client.peek8(0x2C);
653 print "\n\nATTEMPTING TRANSMISSION!!!"
655 print "Transmitting packet: "
656 #print self.client.packet2str(packet)
658 self.client.txpacket(packet);
661 """@todo: the repeat variable is no longer needed and can be removed """
662 print "\nNow looping on transmit. "
664 for i in range(0,writes):
665 self.client.MCPrts(TXB0=True);
667 time.sleep(period/1000) # pause for period ms before sending again
668 #print time.time()-tic
669 #starttime = time.time();
670 #while((time.time()-starttime < duration)):
671 # self.client.MCPrts(TXB0=True);
672 # print "MSG printed"
674 for i in range(0,writes):
675 self.client.MCPrts(TXB0=True);
676 print "messages injected"
681 TXB0CTRL = self.client.peek8(0x30);
683 print "Tx Errors: %3d" % self.client.peek8(0x1c);
684 print "Rx Errors: %3d" % self.client.peek8(0x1d);
685 print "EFLG register: %02x" % self.client.peek8(0x2d);
686 print "TXB0CTRL: %02x" %TXB0CTRL;
687 print "CANINTF: %02x\n" %self.client.peek8(0x2C);
689 while(TXB0CTRL | 0x00 != 0x00):
691 TXB0CTRL = self.client.peek8(0x30);
692 if (checkcount %30 ==0):
693 print "Tx Errors: %3d" % self.client.peek8(0x1c);
694 print "Rx Errors: %3d" % self.client.peek8(0x1d);
695 print "EFLG register: %02x" % self.client.peek8(0x2d);
696 print "TXB0CTRL: %02x" %TXB0CTRL;
697 print "CANINTF: %02x\n" %self.client.peek8(0x2C);
700 def setRate(self,freq):
702 This method will reset the frequency that the MCP2515 expects the CAN bus to be on.
705 @param freq: Frequency of the CAN bus
707 self.client.MCPsetrate(freq);
711 # This will write the data provided in the packets which is expected to be a list of lists
712 # of the following form:
713 # for a given row = packets[i]
714 # row[0] time delay relative to the last packet. if 0 or empty there will be no delay
715 # row[1] = Standard ID (integer)
716 # row[2] = Data Length (0-8) (if it is zero we assume an Remote Transmit Request)
717 # row[3] = Data Byte 0
718 # row[4] = Data Byte 1
719 # .... up to Data Byte 8 ( THIS ASSUMES A PACKET OF LENGTH 8!!!
720 def writeData(self,packets,freq):
721 self.client.serInit()
724 if( row[0] != 0 and row[0] != ""):
727 #### split SID into different regs
728 SIDlow = (sID & 0x07) << 5; # get SID bits 2:0, rotate them to bits 7:5
729 SIDhigh = (sID >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
730 packet = [SIDhigh,SIDlow,0x00,0x00,0x08]
733 for i in range(3,dlc+3):
734 packet.append(row[i])
736 self.client.txpacket(packet)
742 if __name__ == "__main__":
744 parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description='''\
746 Run commands on the MCP2515. Valid commands are:
750 peek 0x(start) [0x(stop)]
760 parser.add_argument('verb', choices=['info', 'test','peek', 'reset', 'sniff', 'freqtest','snifftest', 'spit', 'packet']);
761 parser.add_argument('-f', '--freq', type=int, default=500, help='The desired frequency (kHz)', choices=[100, 125, 250, 500, 1000]);
762 parser.add_argument('-t','--time', type=int, default=15, help='The duration to run the command (s)');
763 parser.add_argument('-o', '--output', default=None,help='Output file');
764 parser.add_argument("-d", "--description", help='Description of experiment (included in the output file)', default="");
765 parser.add_argument('-v',"--verbose",action='store_false',help='-v will stop packet output to terminal', default=True);
766 parser.add_argument('-c','--comment', help='Comment attached to ech packet uploaded',default=None);
767 parser.add_argument('-b', '--debug', action='store_true', help='-b will turn on debug mode, printing packet status', default=False);
768 parser.add_argument('-a', '--standardid', type=int, action='append', help='Standard ID to accept with filter 0 [1, 2, 3, 4, 5]', default=None);
769 parser.add_argument('-x', '--faster', action='store_true', help='-x will use "fast packet recieve," which may duplicate packets and/or cause other weird behavior.', default=False);
770 parser.add_argument('-r', '--repeat', action='store_true', help='-r with "spit" will continuously send the inputted packet. This will put the GoodTHOPTHER into an infinite loop.', default=False);
771 parser.add_argument('-db0', '--databyte0', type=int, default = None, help='-db0 to filter for a specfic data byte');
772 parser.add_argument('-db1', '--databyte1', type=int, default = None, help='-db0 to filter for a specfic data byte');
776 args = parser.parse_args();
779 filename = args.output
780 description = args.description
781 verbose = args.verbose
782 comments = args.comment
784 standardid = args.standardid
790 comm = GoodFETMCPCANCommunication("./");
792 if(args.verb=="packet"):
793 comm.filterForPacket(standardid=standardid[0], DB0=db0, DB1=db1, verbose= True)
795 ##########################
797 ##########################
799 # Prints MCP state info
801 if(args.verb=="info"):
805 ##########################
807 ##########################
811 if(args.verb=="reset"):
814 ##########################
816 ##########################
818 # runs in ListenOnly mode
819 # utility function to pull info off the car's CAN bus
822 if(args.verb=="sniff"):
823 comm.sniff(freq=freq,duration=duration,description=description,verbose=verbose,comment=comments,filename=filename, standardid=standardid, debug=debug, faster=faster, db0=db0, db1=db1)
825 ##########################
827 ##########################
829 # runs in NORMAL mode
830 # intended for NETWORKED MCP chips to verify proper operation
833 if(args.verb=="snifftest"):
834 comm.sniffTest(freq=freq)
837 ##########################
839 ##########################
841 # runs in LISTEN ONLY mode
842 # tests bus for desired frequency --> sniffs bus for specified length of time and reports
843 # if packets were properly formatted
847 if(args.verb=="freqtest"):
848 comm.freqtest(freq=freq)
852 ##########################
854 ##########################
856 # """ An intelligent sniffer, decodes message format """
857 # """ More features to be added soon """
858 if(args.verb=="isniff"):
859 comm.isniff(freq=freq)
862 ##########################
864 ##########################
866 # Runs in LOOPBACK mode
867 # self-check diagnostic
868 # wasn't working before due to improperly formatted packet
870 # ...add automatic packet check rather than making user verify successful packet
871 if(args.verb=="test"):
874 if(args.verb=="peek"):
877 start=int(sys.argv[2],16);
880 stop=int(sys.argv[3],16);
881 print "Peeking from %04x to %04x." % (start,stop);
883 print "%04x: %02x" % (start,client.peek8(start));
886 ##########################
888 ##########################
890 # Basic packet transmission
891 # runs in NORMAL MODE!
893 # checking TX error flags--> currently throwing error flags on every
894 # transmission (travis thinks this is because we're sniffing in listen-only
895 # and thus not generating an ack bit on the recieving board)
896 if(args.verb=="spit"):
897 comm.spitSingle(freq=freq, standardid=standardid,duration=duration, repeat=repeat, debug=debug)