107b6eafc141b25226c1bdab7bd77892c269215b
[goodfet] / client / GoodFETMCPCANCommunication.py
1 #!/usr/bin/env python
2 # GoodFET SPI Flash Client
3 #
4 # (C) 2012 Travis Goodspeed <travis at radiantmachines.com>
5 #
6 #
7 # Ted's working copy
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
11 #
12 #
13
14 import sys;
15 import binascii;
16 import array;
17 import csv, time, argparse;
18 import datetime
19 import os
20 from random import randrange
21 from GoodFETMCPCAN import GoodFETMCPCAN;
22 from intelhex import IntelHex;
23
24 class GoodFETMCPCANCommunication:
25     
26     def __init__(self):
27        self.client=GoodFETMCPCAN();
28        self.client.serInit()
29        self.client.MCPsetup();
30        self.DATALOCATION = "../../contrib/ThayerData/"
31        
32
33     
34     def printInfo(self):
35         
36         self.client.MCPreqstatConfiguration();
37         
38         print "MCP2515 Info:\n\n";
39         
40         print "Mode: %s" % self.client.MCPcanstatstr();
41         print "Read Status: %02x" % self.client.MCPreadstatus();
42         print "Rx Status:   %02x" % self.client.MCPrxstatus();
43         print "Error Flags:  %02x" % self.client.peek8(0x2D);
44         print "Tx Errors:  %3d" % self.client.peek8(0x1c);
45         print "Rx Errors:  %3d\n" % self.client.peek8(0x1d);
46         
47         print "Timing Info:";
48         print "CNF1: %02x" %self.client.peek8(0x2a);
49         print "CNF2: %02x" %self.client.peek8(0x29);
50         print "CNF3: %02x\n" %self.client.peek8(0x28);
51         print "RXB0 CTRL: %02x" %self.client.peek8(0x60);
52         print "RXB1 CTRL: %02x" %self.client.peek8(0x70);
53         
54         print "RX Info:";
55         print "RXB0: %02x" %self.client.peek8(0x60);
56         print "RXB1: %02x" %self.client.peek8(0x70);
57         print "RXB0 masks: %02x, %02x, %02x, %02x" %(self.client.peek8(0x20), self.client.peek8(0x21), self.client.peek8(0x22), self.client.peek8(0x23));
58         print "RXB1 masks: %02x, %02x, %02x, %02x" %(self.client.peek8(0x24), self.client.peek8(0x25), self.client.peek8(0x26), self.client.peek8(0x27));
59
60         
61         print "RX Buffers:"
62         packet0=self.client.readrxbuffer(0);
63         packet1=self.client.readrxbuffer(1);
64         for foo in [packet0, packet1]:
65            print self.client.packet2str(foo);
66            
67     def reset(self):
68         self.client.MCPsetup();
69     
70     
71     ##########################
72     #   SNIFF
73     ##########################
74          
75     def sniff(self,freq,duration,description, verbose=True, comment=None, filename=None, standardid=None, debug=False, faster=False, parsed=True, data = None):
76         
77         #reset eveything on the chip
78         self.client.serInit() 
79         self.reset()
80           
81         #### ON-CHIP FILTERING
82         if(standardid != None):
83             if( comment == None):
84                 comment = ""
85             self.client.MCPreqstatConfiguration();  
86             self.client.poke8(0x60,0x26); # set RXB0 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RMX0=1, BUKT=1)
87             self.client.poke8(0x20,0xFF); #set buffer 0 mask 1 (SID 10:3) to FF
88             self.client.poke8(0x21,0xE0); #set buffer 0 mask 2 bits 7:5 (SID 2:0) to 1s
89             if(len(standardid)>2):
90                self.client.poke8(0x70,0x20); # set RXB1 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RMX0=1)
91                self.client.poke8(0x24,0xFF); #set buffer 1 mask 1 (SID 10:3) to FF
92                self.client.poke8(0x25,0xE0); #set buffer 1 mask 2 bits 7:5 (SID 2:0) to 1s 
93             
94             for filter,ID in enumerate(standardid):
95         
96                if (filter==0):
97                 RXFSIDH = 0x00;
98                 RXFSIDL = 0x01;
99                elif (filter==1):
100                 RXFSIDH = 0x04;
101                 RXFSIDL = 0x05;
102                elif (filter==2):
103                 RXFSIDH = 0x08;
104                 RXFSIDL = 0x09;
105                elif (filter==3):
106                 RXFSIDH = 0x10;
107                 RXFSIDL = 0x11;
108                elif (filter==4):
109                 RXFSIDH = 0x14;
110                 RXFSIDL = 0x15;
111                else:
112                 RXFSIDH = 0x18;
113                 RXFSIDL = 0x19;
114         
115                #### split SID into different regs
116                SIDlow = (ID & 0x07) << 5;  # get SID bits 2:0, rotate them to bits 7:5
117                SIDhigh = (ID >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
118                
119                #write SID to regs 
120                self.client.poke8(RXFSIDH,SIDhigh);
121                self.client.poke8(RXFSIDL, SIDlow);
122         
123                if (verbose == True):
124                    print "Filtering for SID %d (0x%02xh) with filter #%d"%(ID, ID, filter);
125                comment += ("f%d" %(ID))
126         
127         
128         self.client.MCPsetrate(freq);
129         
130         # This will handle the files so that we do not loose them. each day we will create a new csv file
131         if( filename==None):
132             #get folder information (based on today's date)
133             now = datetime.datetime.now()
134             datestr = now.strftime("%Y%m%d")
135             path = self.DATALOCATION+datestr+".csv"
136             filename = path
137             
138         
139         outfile = open(filename,'a');
140         dataWriter = csv.writer(outfile,delimiter=',');
141         dataWriter.writerow(['# Time     Error        Bytes 1-13']);
142         dataWriter.writerow(['#' + description])
143         
144         self.client.MCPreqstatNormal();
145         print "Listening...";
146         packetcount = 0;
147         starttime = time.time();
148         
149         while((time.time()-starttime < duration)):
150             
151             if(faster):
152                 packet=self.client.fastrxpacket();
153             else:
154                 packet=self.client.rxpacket();
155                 
156             #add the data to list if the pointer was included
157             if(data != None):
158                 data.append(packet)
159             
160             if(debug == True):
161                 #check packet status
162                 MCPstatusReg = self.client.MCPrxstatus();
163                 messagestat=MCPstatusReg&0xC0;
164                 messagetype=MCPstatusReg&0x18;
165                 if(messagestat == 0xC0):
166                     print "Message in both buffers; message type is %02x (0x00 is standard data, 0x08 is standard remote)." %messagetype
167                 elif(messagestat == 0x80):
168                     print "Message in RXB1; message type is %02x (0x00 is standard data, 0x08 is standard remote)." %messagetype
169                 elif(messagestat == 0x40):
170                     print "Message in RXB0; message type is %02x (0x00 is standard data, 0x08 is standard remote)." %messagetype
171                 elif(messagestat == 0x00):
172                     print "No messages in buffers."
173             
174             if packet!=None:
175                 
176                 packetcount+=1;
177                 row = [];
178                 row.append("%f"%time.time());
179                 
180                 if( verbose==True):
181                     #if we want to print a parsed message
182                     if( parsed == True):
183 #                        packetParsed = self.client.packet2parsed(packet)
184 #                        sId = packetParsed.get('sID')
185 #                        msg = "sID: %04d" %sId
186 #                        if( packetParsed.get('eID')):
187 #                            msg += " eID: %d" %packetParsed.get('eID')
188 #                        msg += " rtr: %d"%packetParsed['rtr']
189 #                        length = packetParsed['length']
190 #                        msg += " length: %d"%length
191 #                        msg += " data:"
192 #                        for i in range(0,length):
193 #                            dbidx = 'db%d'%i
194 #                            msg +=" %03d"% ord(packetParsed[dbidx])
195                         msg = self.client.packet2parsedstr(packet)
196                         print msg
197                     # if we want to print just the message as it is read off the chip
198                     else:
199                         print self.client.packet2str(packet)
200                 
201                 if(debug == True):
202                     
203                     #check overflow
204                     MCPeflgReg=self.client.peek8(0x2D);
205                     print"EFLG register equals: %x" %MCPeflgReg;
206                     if((MCPeflgReg & 0xC0)==0xC0):
207                         print "WARNING: BOTH overflow flags set. Missed a packet. Clearing and proceeding."
208                     elif(MCPeflgReg & 0x80):
209                         print "WARNING: RXB1 overflow flag set. A packet has been missed. Clearing and proceeding."
210                     elif(MCPeflgReg & 0x40):
211                         print "WARNING: RXB0 overflow flag set. A packet has been missed. Clearing and proceeding."
212                     self.client.MCPbitmodify(0x2D,0xC0,0x00);
213                     print"EFLG register set to: %x" % self.client.peek(0x2D);
214                 
215                     #check for errors
216                     if (self.client.peek8(0x2C) & 0x80):
217                         self.client.MCPbitmodify(0x2C,0x80,0x00);
218                         print "ERROR: Malformed packet recieved: " + self.client.packet2str(packet);
219                         row.append(1);
220                     else:
221                         row.append(0);
222                 else:
223                     row.append(0);  #since we don't check for errors if we're not in debug mode...
224                             
225                 row.append(comment)
226                 #how long the sniff was for
227                 row.append(duration)
228                 #boolean that tells us if there was filtering. 0 == no filters, 1 == filters
229                 if(standardid != None):
230                     row.append(1)
231                 else:
232                     row.append(0)
233                 #write packet to file
234                 for byte in packet:
235                     row.append("%02x"%ord(byte));
236                 dataWriter.writerow(row);
237         
238         outfile.close()
239         print "Listened for %d seconds, captured %d packets." %(duration,packetcount);
240         return packetcount
241         
242         
243     def filterStdSweep(self, freq, low, high, time = 5):
244         msgIDs = []
245         self.client.serInit()
246         self.client.MCPsetup()
247         for i in range(low, high+1, 6):
248             print "sniffing id: %d, %d, %d, %d, %d, %d" % (i,i+1,i+2,i+3,i+4,i+5)
249             comment= "sweepFilter: "
250             #comment = "sweepFilter_%d_%d_%d_%d_%d_%d" % (i,i+1,i+2,i+3,i+4,i+5)
251             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)
252             count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [i, i+1, i+2, i+3, i+4, i+5])
253             if( count != 0):
254                 for j in range(i,i+5):
255                     comment = "sweepFilter: "
256                     #comment = "sweepFilter: %d" % (j)
257                     description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d " % j
258                     count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [j, j, j, j])
259                     if( count != 0):
260                         msgIDs.append(j)
261         return msgIDs
262     
263     def sweepRandom(self, freq, number = 5, time = 200):
264         msgIDs = []
265         ids = []
266         self.client.serInit()
267         self.client.MCPsetup()
268         for i in range(0,number+1,6):
269             idsTemp = []
270             comment = "sweepFilter: "
271             for j in range(0,6,1):
272                 id = randrange(2047)
273                 #comment += "_%d" % id
274                 idsTemp.append(id)
275                 ids.append(id)
276             print comment
277             description = "Running a sweep filer for all the possible standard IDs. This runs the following : " + comment
278             count = self.sniff(freq=freq, duration=time, description=description, comment = comment, standardid = idsTemp)
279             if( count != 0):
280                 for element in idsTemp:
281                     #comment = "sweepFilter: %d" % (element)
282                     comment="sweepFilter: "
283                     description = "Running a sweep filer for all the possible standard IDs. This run filters for: %d " % element
284                     count = self.sniff(freq=freq, duration = time, description = description,comment = comment, standardid = [element, element, element])
285                     if( count != 0):
286                         msgIDs.append(j)
287         return msgIDs, ids
288     
289     def sniffTest(self, freq):
290         
291         rate = freq;
292         
293         print "Calling MCPsetrate for %i." %rate;
294         self.client.MCPsetrate(rate);
295         self.client.MCPreqstatNormal();
296         
297         print "Mode: %s" % self.client.MCPcanstatstr();
298         print "CNF1: %02x" %self.client.peek8(0x2a);
299         print "CNF2: %02x" %self.client.peek8(0x29);
300         print "CNF3: %02x\n" %self.client.peek8(0x28);
301         
302         while(1):
303             packet=self.client.rxpacket();
304             
305             if packet!=None:                
306                 if (self.client.peek8(0x2C) & 0x80):
307                     self.client.MCPbitmodify(0x2C,0x80,0x00);
308                     print "malformed packet recieved: "+ self.client.packet2str(packet);
309                 else:
310                     print "properly formatted packet recieved" + self.client.packet2str(packet);
311    
312     
313     def freqtest(self,freq):
314         
315         self.client.MCPsetup();
316
317         self.client.MCPsetrate(freq);
318         self.client.MCPreqstatListenOnly();
319     
320         print "CAN Freq Test: %3d kHz" %freq;
321     
322         x = 0;
323         errors = 0;
324     
325         starttime = time.time();
326         while((time.time()-starttime < args.time)):
327             packet=self.client.rxpacket();
328             if packet!=None:
329                 x+=1;
330                 
331                 if (self.client.peek8(0x2C) & 0x80):
332                     print "malformed packet recieved"
333                     errors+=1;
334                     self.client.MCPbitmodify(0x2C,0x80,0x00);
335                 else:         
336                     print self.client.packet2str(packet);
337     
338         print "Results for %3.1d kHz: recieved %3d packets, registered %3d RX errors." %(freq, x, errors);
339     
340
341     def isniff(self,freq):
342         """ An intelligent sniffer, decodes message format """
343         """ More features to be added soon """
344         
345         self.client.MCPsetrate(freq);
346         self.client.MCPreqstatListenOnly();
347         while 1:
348             packet=self.client.rxpacket();
349             if packet!=None:
350                 plist=[];
351                 for byte in packet:
352                     plist.append(byte);
353                 arbid=plist[0:2];
354                 eid=plist[2:4];
355                 dlc=plist[4:5];
356                 data=plist[5:13];         
357                 print "\nArbID: " + self.client.packet2str(arbid);
358                 print "EID: " + self.client.packet2str(eid);
359                 print "DLC: " + self.client.packet2str(dlc);
360                 print "Data: " + self.client.packet2str(data);
361
362     def test(self):
363         
364         comm.reset();
365         print "Just reset..."
366         print "EFLG register:  %02x" % self.client.peek8(0x2d);
367         print "Tx Errors:  %3d" % self.client.peek8(0x1c);
368         print "Rx Errors:  %3d" % self.client.peek8(0x1d);
369         print "CANINTF: %02x"  %self.client.peek8(0x2C);
370         self.client.MCPreqstatConfiguration();
371         self.client.poke8(0x60,0x66);
372         self.client.MCPsetrate(500);
373         self.client.MCPreqstatNormal();
374         print "In normal mode now"
375         print "EFLG register:  %02x" % self.client.peek8(0x2d);
376         print "Tx Errors:  %3d" % self.client.peek8(0x1c);
377         print "Rx Errors:  %3d" % self.client.peek8(0x1d);
378         print "CANINTF: %02x"  %self.client.peek8(0x2C);
379         print "Waiting on packets.";
380         checkcount = 0;
381         packet=None;
382         while(1):
383             packet=self.client.rxpacket();
384             if packet!=None:
385                 print "Message recieved: %s" % self.client.packet2str(packet);
386             else:
387                 checkcount=checkcount+1;
388                 if (checkcount%30==0):
389                     print "EFLG register:  %02x" % self.client.peek8(0x2d);
390                     print "Tx Errors:  %3d" % self.client.peek8(0x1c);
391                     print "Rx Errors:  %3d" % self.client.peek8(0x1d);
392                     print "CANINTF: %02x"  %self.client.peek8(0x2C);
393
394     
395     
396     
397     def addFilter(self,standardid, verbose= True):
398         comment = None
399         ### ON-CHIP FILTERING
400         if(standardid != None):
401             self.client.MCPreqstatConfiguration();  
402             self.client.poke8(0x60,0x26); # set RXB0 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RMX0=1, BUKT=1)
403             self.client.poke8(0x20,0xFF); #set buffer 0 mask 1 (SID 10:3) to FF
404             self.client.poke8(0x21,0xE0); #set buffer 0 mask 2 bits 7:5 (SID 2:0) to 1s
405             if(len(standardid)>2):
406                self.client.poke8(0x70,0x20); # set RXB1 CTRL register to ONLY accept STANDARD messages with filter match (RXM1=0, RMX0=1)
407                self.client.poke8(0x24,0xFF); #set buffer 1 mask 1 (SID 10:3) to FF
408                self.client.poke8(0x25,0xE0); #set buffer 1 mask 2 bits 7:5 (SID 2:0) to 1s 
409             
410             for filter,ID in enumerate(standardid):
411         
412                if (filter==0):
413                 RXFSIDH = 0x00;
414                 RXFSIDL = 0x01;
415                elif (filter==1):
416                 RXFSIDH = 0x04;
417                 RXFSIDL = 0x05;
418                elif (filter==2):
419                 RXFSIDH = 0x08;
420                 RXFSIDL = 0x09;
421                elif (filter==3):
422                 RXFSIDH = 0x10;
423                 RXFSIDL = 0x11;
424                elif (filter==4):
425                 RXFSIDH = 0x14;
426                 RXFSIDL = 0x15;
427                else:
428                 RXFSIDH = 0x18;
429                 RXFSIDL = 0x19;
430         
431                #### split SID into different regs
432                SIDlow = (ID & 0x07) << 5;  # get SID bits 2:0, rotate them to bits 7:5
433                SIDhigh = (ID >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
434                
435                #write SID to regs 
436                self.client.poke8(RXFSIDH,SIDhigh);
437                self.client.poke8(RXFSIDL, SIDlow);
438         
439                if (verbose == True):
440                    print "Filtering for SID %d (0x%02xh) with filter #%d"%(ID, ID, filter);
441                
442         self.client.MCPreqstatNormal();
443     
444     
445     # this will sweep through the given ids to request a packet and then sniff on that
446     # id for a given amount duration. This will be repeated the number of attempts time
447     
448     #at the moment this is set to switch to the next id once  a message is identified
449     def rtrSweep(self,freq,lowID,highID, attempts = 1,duration = 1, verbose = True):
450         #set up file
451         now = datetime.datetime.now()
452         datestr = now.strftime("%Y%m%d")
453         path = self.DATALOCATION+datestr+"_rtr.csv"
454         filename = path
455         outfile = open(filename,'a');
456         dataWriter = csv.writer(outfile,delimiter=',');
457         dataWriter.writerow(['# Time     Error        Bytes 1-13']);
458         dataWriter.writerow(['#' + "rtr sweep from %d to %d"%(lowID,highID)])
459         print "started"
460         #self.client.serInit()
461         #self.spitSetup(freq)
462         for i in range(lowID,highID+1, 1):
463             self.client.serInit()
464             self.spitSetup(freq)
465             standardid = [i, i, i, i]
466             #set filters
467             self.addFilter(standardid, verbose = True)
468             
469             #### split SID into different areas
470             SIDlow = (standardid[0] & 0x07) << 5;  # get SID bits 2:0, rotate them to bits 7:5
471             SIDhigh = (standardid[0] >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
472             #create RTR packet
473             packet = [SIDhigh, SIDlow, 0x00,0x00,0x40]
474             dataWriter.writerow(["#requested id %d"%i])
475             #self.client.poke8(0x2C,0x00);  #clear the CANINTF register; we care about bits 0 and 1 (RXnIF flags) which indicate a message is being held 
476             #clear buffer
477             packet1 = self.client.rxpacket();
478             packet2 = self.client.rxpacket();
479             #send in rtr request
480             self.client.txpacket(packet)
481             ## listen for 2 packets. one should be the rtr we requested the other should be
482             ## a new packet response
483             starttime = time.time()
484             while ((time.time() - starttime) < duration):
485                 packet = self.client.rxpacket()
486                 if( packet == None):
487                     continue
488                 row = []
489                 row.append("%f"%time.time()) #timestamp
490                 row.append(0) #error flag (not checkign)
491                 row.append("rtrRequest_%d"%i) #comment
492                 row.append(duration) #sniff time
493                 row.append(1) # filtering boolean
494                 for byte in packet:
495                     row.append("%02x"%ord(byte));
496                 dataWriter.writerow(row)
497                 print self.client.packet2parsedstr(packet)
498 #            packet1=self.client.rxpacket();
499 #            packet2=self.client.rxpacket();
500 #            if( packet1 != None and packet2 != None):
501 #                print "packets recieved :\n "
502 #                print self.client.packet2parsedstr(packet1);
503 #                print self.client.packet2parsedstr(packet2);
504 #                continue
505 #            elif( packet1 != None):
506 #                print self.client.packet2parsedstr(packet1)
507 #            elif( packet2 != None):
508 #                print self.client.packet2parsedstr(packet2)
509             trial= 2;
510             # for each trial
511             while( trial <= attempts):
512                 print "trial: ", trial
513                 self.client.MCPrts(TXB0=True);
514                 starttime = time.time()
515                 # this time we will sniff for the given amount of time to see if there is a
516                 # time till the packets come in
517                 while( (time.time()-starttime) < duration):
518                     packet=self.client.rxpacket();
519                     row = []
520                     row.append("%f"%time.time()) #timestamp
521                     row.append(0) #error flag (not checking)
522                     row.append("rtrRequest_%d"%i) #comment
523                     row.append(duration) #sniff time
524                     row.append(1) # filtering boolean
525                     for byte in packet:
526                         row.append("%02x"%ord(byte));
527                     dataWriter.writerow(row)
528                     print self.client.packet2parsedstr(packet)
529 #                    packet2=self.client.rxpacket();
530 #                    
531 #                    if( packet1 != None and packet2 != None):
532 #                        print "packets recieved :\n "
533 #                        print self.client.packet2parsedstr(packet1);
534 #                        print self.client.packet2parsedstr(packet2);
535 #                        #break
536 #                    elif( packet1 != None):
537 #                        print "just packet1"
538 #                        print self.client.packet2parsedstr(packet1)
539 #                    elif( packet2 != None):
540 #                        print "just packet2"
541 #                        print self.client.packet2parsedstr(packet2)
542                 trial += 1
543         print "sweep complete"
544         outfile.close()
545         
546     def spitSetup(self,freq):
547         self.reset();
548         self.client.MCPsetrate(freq);
549         self.client.MCPreqstatNormal();
550         
551     
552     def spitSingle(self,freq, standardid, repeat, duration = None, debug = False, packet = None):
553         self.spitSetup(freq);
554         spit(self,freq, standardid, repeat, duration = None, debug = False, packet = None)
555
556     def spit(self,freq, standardid, repeat, duration = None, debug = False, packet = None):
557     
558
559         #### split SID into different regs
560         SIDlow = (standardid[0] & 0x07) << 5;  # get SID bits 2:0, rotate them to bits 7:5
561         SIDhigh = (standardid[0] >> 3) & 0xFF; # get SID bits 10:3, rotate them to bits 7:0
562         
563         if(packet == None):
564             
565             # if no packet, RTR for inputted arbID
566             # so packet to transmit is SID + padding out EID registers + RTR request (set bit 6, clear lower nibble of DLC register)
567             packet = [SIDhigh, SIDlow, 0x00,0x00,0x40] 
568         
569         
570                 #packet = [SIDhigh, SIDlow, 0x00,0x00, # pad out EID regs
571                 #         0x08, # bit 6 must be set to 0 for data frame (1 for RTR) 
572                 #        # lower nibble is DLC                   
573                 #        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0xFF]
574         else:
575
576             # if we do have a packet, packet is SID + padding out EID registers + DLC of 8 + packet
577             #
578             #    TODO: allow for variable-length packets
579             #
580             packet = [SIDhigh, SIDlow, 0x00,0x00, # pad out EID regs
581                   0x08, # bit 6 must be set to 0 for data frame (1 for RTR) 
582                   # lower nibble is DLC                   
583                  packet[0],packet[1],packet[2],packet[3],packet[4],packet[5],packet[6],packet[7]]
584             
585         
586         if(debug):
587             if self.client.MCPcanstat()>>5!=0:
588                 print "Warning: currently in %s mode. NOT in normal mode! May not transmit.\n" %self.client.MCPcanstatstr();
589             print "\nInitial state:"
590             print "Tx Errors:  %3d" % self.client.peek8(0x1c);
591             print "Rx Errors:  %3d" % self.client.peek8(0x1d);
592             print "Error Flags:  %02x\n" % self.client.peek8(0x2d);
593             print "TXB0CTRL: %02x" %self.client.peek8(0x30);
594             print "CANINTF: %02x\n"  %self.client.peek8(0x2C);
595             print "\n\nATTEMPTING TRANSMISSION!!!"
596         
597                 
598         print "Transmitting packet: "
599         print self.client.packet2str(packet)
600                 
601         self.client.txpacket(packet);
602             
603         if repeat:
604             print "\nNow looping on transmit. "
605             if duration!= None:
606                 starttime = time.time();
607                 while((time.time()-starttime < duration)):
608                     self.client.MCPrts(TXB0=True);
609                     print "MSG printed"
610             else:
611                 while(1): 
612                     self.client.MCPrts(TXB0=True);
613         print "messages injected"
614         
615         # MORE DEBUGGING        
616         if(debug): 
617             checkcount = 0;
618             TXB0CTRL = self.client.peek8(0x30);
619         
620             print "Tx Errors:  %3d" % self.client.peek8(0x1c);
621             print "Rx Errors:  %3d" % self.client.peek8(0x1d);
622             print "EFLG register:  %02x" % self.client.peek8(0x2d);
623             print "TXB0CTRL: %02x" %TXB0CTRL;
624             print "CANINTF: %02x\n"  %self.client.peek8(0x2C);
625         
626             while(TXB0CTRL | 0x00 != 0x00):
627                 checkcount+=1;
628                 TXB0CTRL = self.client.peek8(0x30);
629                 if (checkcount %30 ==0):
630                     print "Tx Errors:  %3d" % self.client.peek8(0x1c);
631                     print "Rx Errors:  %3d" % self.client.peek8(0x1d);
632                     print "EFLG register:  %02x" % self.client.peek8(0x2d);
633                     print "TXB0CTRL: %02x" %TXB0CTRL;
634                     print "CANINTF: %02x\n"  %self.client.peek8(0x2C);
635
636
637     def setRate(self,freq):
638         self.client.MCPsetrate(freq);
639         
640
641
642
643 if __name__ == "__main__":  
644
645     parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description='''\
646     
647         Run commands on the MCP2515. Valid commands are:
648         
649             info 
650             test
651             peek 0x(start) [0x(stop)]
652             reset
653             
654             sniff 
655             freqtest
656             snifftest
657             spit
658         ''')
659         
660     
661     parser.add_argument('verb', choices=['info', 'test','peek', 'reset', 'sniff', 'freqtest','snifftest', 'spit']);
662     parser.add_argument('-f', '--freq', type=int, default=500, help='The desired frequency (kHz)', choices=[100, 125, 250, 500, 1000]);
663     parser.add_argument('-t','--time', type=int, default=15, help='The duration to run the command (s)');
664     parser.add_argument('-o', '--output', default=None,help='Output file');
665     parser.add_argument("-d", "--description", help='Description of experiment (included in the output file)', default="");
666     parser.add_argument('-v',"--verbose",action='store_false',help='-v will stop packet output to terminal', default=True);
667     parser.add_argument('-c','--comment', help='Comment attached to ech packet uploaded',default=None);
668     parser.add_argument('-b', '--debug', action='store_true', help='-b will turn on debug mode, printing packet status', default=False);
669     parser.add_argument('-a', '--standardid', type=int, action='append', help='Standard ID to accept with filter 0 [1, 2, 3, 4, 5]', default=None);
670     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);
671     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);
672     
673     
674     args = parser.parse_args();
675     freq = args.freq
676     duration = args.time
677     filename = args.output
678     description = args.description
679     verbose = args.verbose
680     comments = args.comment
681     debug = args.debug
682     standardid = args.standardid
683     faster=args.faster
684     repeat = args.repeat
685
686     comm = GoodFETMCPCANCommunication();
687     
688     ##########################
689     #   INFO
690     ##########################
691     #
692     # Prints MCP state info
693     #
694     if(args.verb=="info"):
695         comm.printInfo()
696         
697            
698     ##########################
699     #   RESET
700     ##########################
701     #
702     #
703             
704     if(args.verb=="reset"):
705         comm.reset()
706         
707     ##########################
708     #   SNIFF
709     ##########################
710     #
711     #   runs in ListenOnly mode
712     #   utility function to pull info off the car's CAN bus
713     #
714     
715     if(args.verb=="sniff"):
716         comm.sniff(freq=freq,duration=duration,description=description,verbose=verbose,comment=comments,filename=filename, standardid=standardid, debug=debug, faster=faster)    
717                     
718     ##########################
719     #   SNIFF TEST
720     ##########################
721     #
722     #   runs in NORMAL mode
723     #   intended for NETWORKED MCP chips to verify proper operation
724     #
725        
726     if(args.verb=="snifftest"):
727         comm.sniffTest(freq=freq)
728         
729         
730     ##########################
731     #   FREQ TEST
732     ##########################
733     #
734     #   runs in LISTEN ONLY mode
735     #   tests bus for desired frequency --> sniffs bus for specified length of time and reports
736     #   if packets were properly formatted
737     #
738     #
739     
740     if(args.verb=="freqtest"):
741         comm.freqtest(freq=freq)
742
743
744
745     ##########################
746     #   iSniff
747     ##########################
748     #
749     #    """ An intelligent sniffer, decodes message format """
750     #    """ More features to be added soon """
751     if(args.verb=="isniff"):
752         comm.isniff(freq=freq)
753                 
754                 
755     ##########################
756     #   MCP TEST
757     ##########################
758     #
759     #   Runs in LOOPBACK mode
760     #   self-check diagnostic
761     #   wasn't working before due to improperly formatted packet
762     #
763     #   ...add automatic packet check rather than making user verify successful packet
764     if(args.verb=="test"):
765         comm.test()
766         
767     if(args.verb=="peek"):
768         start=0x0000;
769         if(len(sys.argv)>2):
770             start=int(sys.argv[2],16);
771         stop=start;
772         if(len(sys.argv)>3):
773             stop=int(sys.argv[3],16);
774         print "Peeking from %04x to %04x." % (start,stop);
775         while start<=stop:
776             print "%04x: %02x" % (start,client.peek8(start));
777             start=start+1;
778             
779     ##########################
780     #   SPIT
781     ##########################
782     #
783     #   Basic packet transmission
784     #   runs in NORMAL MODE!
785     # 
786     #   checking TX error flags--> currently throwing error flags on every
787     #   transmission (travis thinks this is because we're sniffing in listen-only
788     #   and thus not generating an ack bit on the recieving board)
789     if(args.verb=="spit"):
790         comm.spitSingle(freq=freq, standardid=standardid,duration=duration, repeat=repeat, debug=debug)
791
792
793     
794     
795     
796     
797         
798         
799     
800     
801     
802