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