goodfet.ccspi now takes freq in MHz instead of just Hz.
[goodfet] / client / goodfet.ccspi
1 #!/usr/bin/env python
2
3 #GoodFET Chipcon SPI Client
4 # (C) 2011 Travis Goodspeed
5 # Additions 2011-2012 Ryan Speers ryan@rmspeers.com
6
7 #N.B.,
8 #Might be CC2420 Specific
9
10 import sys;
11 import binascii;
12 import array, time;
13
14 from GoodFETCCSPI import GoodFETCCSPI;
15
16 if(len(sys.argv)==1):
17     print "Usage: %s verb [objects]\n" % sys.argv[0];
18     print "%s info" % sys.argv[0];
19     print "%s regs" % sys.argv[0];
20     print "%s test" % sys.argv[0];
21     print "%s peek 0x$start [0x$stop]" % sys.argv[0];
22     print "%s poke 0x$adr 0x$val" % sys.argv[0];
23     print "%s txtest" % sys.argv[0];
24     
25     print "\n%s rssi" % sys.argv[0];
26     print "%s sniff [chan]" % sys.argv[0];
27     print "%s bsniff [chan]" % sys.argv[0];
28     print "%s sniffdissect" % sys.argv[0];
29     
30     print "\n%s txtoscount [-i|-r]   TinyOS BlinkToLED" % sys.argv[0];
31     print "%s reflexjam [channel=11] [delay=0]" % sys.argv[0];
32
33     sys.exit();
34
35 #Initialize FET and set baud rate
36 client=GoodFETCCSPI();
37 client.serInit()
38
39 client.setup();
40
41 #Dummy read.
42 #Might read as all ones if chip has a startup delay.
43
44 if(sys.argv[1]=="carrier"):
45     if len(sys.argv)>2:
46         client.RF_setfreq(eval(sys.argv[2]));
47     while 1:
48         client.RF_carrier();
49     while(1):
50         time.sleep(1);
51
52 if(sys.argv[1]=="modulated_spectrum"):
53     if len(sys.argv)>2:
54         client.RF_setfreq(eval(sys.argv[2]));
55     while 1:
56         client.RF_modulated_spectrum();
57     while(1):
58         time.sleep(1);
59
60 if(sys.argv[1]=="reflexjam" or sys.argv[1]=="reflexjamack"):
61     #Setup the radio to listen promiscously on a frequency
62     client.RF_promiscuity(1);
63     client.RF_autocrc(0);
64     if len(sys.argv)>2:
65         freq=eval(sys.argv[2]);
66         if freq>100:
67             client.RF_setfreq(freq);
68         else:
69             client.RF_setchan(freq);
70     duration=0;
71     if len(sys.argv)>3:
72         duration=eval(sys.argv[3]);
73     client.CC_RFST_RX();
74     print "Reflexively jamming on %i MHz" % (client.RF_getfreq()/10**6);
75     #Now we let the firmware take over, watching for packets and jamming them.
76     #Standard reflexive jam is done with duration=0.
77     #To selectively jam packets that are above a certain length, set duration
78     # to the number of milliseconds needed to jam frames of that length.
79     # Api-Do project has script available to tune/test this duration.
80     #  code.google.com/p/zigbeesecurity (rmspeers)
81     if sys.argv[1]=="reflexjam":
82         client.RF_reflexjam(duration);
83     elif sys.argv[1]=="reflexjamack":
84         client.RF_reflexjam_autoack();
85
86 if(sys.argv[1]=="info"):
87     print "Found   %s" % client.identstr();
88     print "Freq:   %05f MHz" % (client.RF_getfreq()/(10**6));
89     print "Status: %s" % client.status();
90 if(sys.argv[1]=="regs"):
91     for adr in range(0x10,0x40): #*1024):
92         val=client.peek(adr);
93         print "%04x:=0x%04x" % (adr,val);
94 if(sys.argv[1]=="test"):
95     data=client.trans([0x20, 0xde, 0xad]);
96     print "%02x %02x" % (ord(data[1]), ord(data[2]));
97     data=client.trans([0x40|0x20, 0xde, 0xad]);
98     print "%02x %02x" % (ord(data[1]), ord(data[2]));
99 if(sys.argv[1]=="rssi"):
100     if len(sys.argv)>2:
101         freq=eval(sys.argv[2]);
102         if freq>100:
103             client.RF_setfreq(freq);
104         else:
105             client.RF_setchan(freq);
106     print "Listening on %f MHz." % (client.RF_getfreq()/10.0**6);
107         
108     client.strobe(0x02); #Calibrate
109     time.sleep(1);
110     
111     while 1:
112         client.CC_RFST_RX();
113         #client.strobe(0x03); #SRXON
114         rssi=client.RF_getrssi();
115         #client.CC_RFST_IDLE(); #idle
116         time.sleep(0.01);
117         string="";
118         for foo in range(0,rssi>>2):
119             string=("%s."%string);
120         print "%02x %04i %s" % (rssi,rssi, string); 
121
122 if(sys.argv[1]=="sniff" or sys.argv[1]=="sniffdissect"):
123     #Promiscuous mode.
124     client.RF_promiscuity(1);
125     client.RF_autocrc(0);
126     
127     if len(sys.argv)>2:
128         freq=eval(sys.argv[2]);
129         if freq>3000:
130             client.RF_setfreq(freq);
131         elif freq>100:
132             client.RF_setfreq(freq*1000000);
133         else:
134             client.RF_setchan(freq);
135     client.CC_RFST_RX();
136     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
137                                             client.RF_getfreq()/10**6);
138     #Now we're ready to get packets.
139     while 1:
140         packet=None;
141         while packet==None:
142             packet=client.RF_rxpacket();
143         if sys.argv[1]=="sniffdissect":
144             client.printdissect(packet);
145         else:
146             client.printpacket(packet);
147         sys.stdout.flush();
148
149 if(sys.argv[1]=="bsniff"):
150     #Just broadcast.
151     client.RF_promiscuity(0);
152     client.RF_setsmac(0xFFFFFFFF);
153     client.RF_autocrc(1);
154     
155     if len(sys.argv)>2:
156         freq=eval(sys.argv[2]);
157         if freq>100:
158             client.RF_setfreq(freq);
159         else:
160             client.RF_setchan(freq);
161     client.CC_RFST_RX();
162     print "Listening as %010x on %i MHz" % (client.RF_getsmac(),
163                                             client.RF_getfreq()/10**6);
164     #Now we're ready to get packets.
165     while 1:
166         packet=None;
167         while packet==None:
168             packet=client.RF_rxpacket();
169         client.printpacket(packet);
170         sys.stdout.flush();
171
172 if(sys.argv[1]=="txtest"):
173     if len(sys.argv)>2:
174         freq=eval(sys.argv[2]);
175         if freq>100:
176             client.RF_setfreq(freq);
177         else:
178             client.RF_setchan(freq);
179     print "Transmitting DEADBEEF as %010x on %i MHz" % (
180         client.RF_getsmac(),
181         client.RF_getfreq()/10**6);
182     
183     while 1:
184         client.RF_txpacket([0x0f, 0x01, 0x08, 0x82,
185                             0xff, 0xff, 0xff, 0xff,
186                             0xde, 0xad, 0xbe, 0xef,
187                             0xba, 0xbe, 0xc0]);
188
189 if(sys.argv[1]=="txtoscount"):
190     '''
191     Clone of what TinyOS's RadioCountToLeds demo code does.  Specify a
192     channel a TinyOS mote programmed with RadioCountToLeds is on, and
193     this will act as the second device. (ryan@rmspeers.com)
194     '''
195     if (len(sys.argv)<=3):
196         print "Provide -r to work via replays or -i to work via incrementing itself.";
197         sys.exit(1);
198     if (sys.argv[3]=="-r"):
199         client.RF_promiscuity(1);
200     client.RF_autocrc(1);
201     if len(sys.argv)>2:
202         freq=eval(sys.argv[2]);
203         if freq>100:
204             client.RF_setfreq(freq);
205         else:
206             client.RF_setchan(freq);
207     if (sys.argv[3]=="-r"):
208         client.CC_RFST_RX();
209         print "Listening as %010x on %i MHz" % (client.RF_getsmac(), client.RF_getfreq()/10**6);
210     print "Transmitting like the TinyOS CountToRadio program on %i MHz" % (client.RF_getfreq()/10**6);
211     if (sys.argv[3]=="-i"):
212         i = 0;
213         countpkt = [0x0f, 0x41, 0x88, 0xFF, 0x22, 0x00, 0xff, 0xff, 0x01, 0x00, 0x3f, 0x06, 0x00, 0xFF];
214     while 1:
215         if (sys.argv[3]=="-r"): #give -r to do via replays from the other device
216             packet=None;
217             while packet==None:
218                 packet=client.RF_rxpacket();
219             pkt = packet[:14];
220             client.RF_txpacket(pkt);
221         elif (sys.argv[3]=="-i"): #give -i to have it increment and send
222             #Use this code for it to actually do increments itself:
223             pkt = countpkt[:];
224             pkt[3] = i;
225             pkt[13] = i+1;
226             client.RF_txpacket(pkt);
227             if i >= 31: i = 0;
228             else:       i += 1;
229             time.sleep(0.5);
230
231 if(sys.argv[1]=="txpiptest" or sys.argv[1]=="txpipscapy"):
232     if len(sys.argv)>2:
233         freq=eval(sys.argv[2]);
234         if freq>100:
235             client.RF_setfreq(freq);
236         else:
237             client.RF_setchan(freq);
238     print "Transmitting on as %010x on %i MHz" % (
239         client.RF_getsmac(),
240         client.RF_getfreq()/10**6);
241     
242     client.RF_setsync(0xFFFF);
243     
244     while 1:
245         if(sys.argv[1]=="txpiptest"):
246             client.RF_txpacket([
247                     0x7f, 
248                     #Real header, must begin with SFD.
249                     0x00, 0x00, 0x00,
250                     0x00, 0xA7,
251                     
252                     #Length
253                     0x1f, 0x01, 0x08, 0x82,
254                     0xDF, 0xff, 0xff, 0xff,
255                     0xde, 0xad, 0xbe, 0xef,
256                     0xba, 0xbe, 0xc0,
257                     
258                     #Preamble
259                     0x00, 0x00, 0x00,
260                     #SFD
261                     0x00, 0xA7,  #CC2420 SFD
262                     #Packet In Packet
263                     0x0f, 0x01, 0x08, 0x82,
264                     0xff, 0xff, 0xff, 0xff,
265                     0xde, 0xad, 0xbe, 0xef,
266                     0xba, 0xbe, 0xc0,
267                     
268                     0xff, 0xff, 0xff, 0xff,
269                     0xff, 0xff, 0xff, 0xff,
270                     0xff, 0xff, 0xff, 0xff,
271                     0xff, 0xff, 0xff, 0xff,
272                     0xff, 0xff, 0xff, 0xff,
273                     0xff, 0xff, 0xff, 0xff,
274                     0xff, 0xff, 0xff, 0xff,
275                     ]);
276         elif(sys.argv[1]=="txpipscapy"):
277             # NB: Requires Scapy with dot15d4.py layer. (rmspeers)
278             try:
279                 from scapy.all import Dot15d4, Dot15d4FCS, Dot15d4Data, Raw
280                 import struct
281             except ImportError:
282                 print "To use packet building, Scapy must be installed and have the dot15d4 layer present."
283                 print "try: hg clone http://hg.secdev.org/scapy-com";
284                 print "     sudo ./setup.py install";
285             #Overall method is to build from the inner packet outwards in the pkt string
286             # Make inner packet
287             scapyinner = Dot15d4FCS(seqnum=130)/Dot15d4Data()/Raw('\xde\xad\xbe\xef');
288             pkt = str(scapyinner);                  #build inner pkt to bytes, adding FCS automatically
289             pkt = struct.pack('b', len(pkt)) + pkt  #prepend with its length
290             pkt = "\x00\x00\x00\x00\xA7" + pkt      #add preamble and SFD to inner packet
291             # Make outer (wrapping) packet
292             scapyouter = Dot15d4(seqnum=130)/Dot15d4Data(dest_panid=0xffdf)/Raw('\xde\xad\xbe\xef\xba\xbe\xc0') #TODO why need these last 3 bytes?
293             pkt = str(scapyouter) + pkt
294             pkt = struct.pack('b', len(pkt)) + pkt  #prepend with its length
295             pkt = '\x00\x00\x00\x00\xA7' + pkt + ('\xff'*28) #start with preamble/SFD and add 0xff fill at end
296             pkt = struct.pack('b', len(pkt)) + pkt  #prepend with its length (originally used \x7f)
297             client.printpacket(pkt)
298             client.RF_autocrc(1);
299             client.RF_txpacket(pkt)
300
301 if(sys.argv[1]=="peek"):
302     start=0x0000;
303     if(len(sys.argv)>2):
304         start=int(sys.argv[2],16);
305     stop=start;
306     if(len(sys.argv)>3):
307         stop=int(sys.argv[3],16);
308     print "Peeking from %04x to %04x." % (start,stop);
309     while start<=stop:
310         print "%04x: 0x%04x" % (start,client.peek(start));
311         start=start+1;
312 if(sys.argv[1]=="poke"):
313     start=0x0000;
314     val=0x00;
315     if(len(sys.argv)>2):
316         start=int(sys.argv[2],16);
317     if(len(sys.argv)>3):
318         val=int(sys.argv[3],16);
319     print "Poking r%02x to become 0x%04x." % (start,val);
320     
321     client.poke(start,val);
322