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