CCSPI port can now packet sniff 802.15.4!
[goodfet] / client / GoodFETCCSPI.py
1 #!/usr/bin/env python
2 # GoodFET Chipcon RF Radio Client
3
4 # (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
5 #
6 # This code is being rewritten and refactored.  You've been warned!
7
8 import sys, time, string, cStringIO, struct, glob, serial, os;
9
10 from GoodFET import GoodFET;
11
12 class GoodFETCCSPI(GoodFET):
13     CCSPIAPP=0x51;
14     CCversions={0x233d: "CC2420",
15                 }
16     def setup(self):
17         """Move the FET into the CCSPI application."""
18         self.writecmd(self.CCSPIAPP,0x10,0,self.data); #CCSPI/SETUP
19         
20         #Set up the radio for ZigBee
21         self.strobe(0x01);       #SXOSCON
22         self.poke(0x11, 0x0AC2); #MDMCTRL0
23         self.poke(0x12, 0x0500); #MDMCTRL1
24         self.poke(0x1C, 0x007F); #IOCFG0
25         self.poke(0x19, 0x01C4); #SECCTRL0, disabling crypto
26         
27     def ident(self):
28         return self.peek(0x1E); #MANFIDL
29     def identstr(self):
30         manfidl=self.peek(0x1E);
31         #manfidh=self.peek(0x1f);
32         try:
33             return "%s" % (self.CCversions[manfidl]); 
34         except:
35             return "Unknown0x%04x" % manfidl;
36     def trans8(self,byte):
37         """Read and write 8 bits by CCSPI."""
38         data=self.CCSPItrans([byte]);
39         return ord(data[0]);
40     
41     def trans(self,data):
42         """Exchange data by CCSPI."""
43         self.data=data;
44         self.writecmd(self.CCSPIAPP,0x00,len(data),data);
45         return self.data;
46     def strobe(self,reg=0x00):
47         """Strobes a strobe register, returning the status."""
48         data=[reg];
49         self.trans(data);
50         return ord(self.data[0]);
51     def CC_RFST_IDLE(self):
52         """Switch the radio to idle mode, clearing overflows and errors."""
53         self.strobe(0x06); #SRXOFF
54     def CC_RFST_TX(self):
55         """Switch the radio to TX mode."""
56         self.strobe(0x04);  #0x05 for CCA
57     def CC_RFST_RX(self):
58         """Switch the radio to RX mode."""
59         self.strobe(0x03);
60     def CC_RFST_CAL(self):
61         """Calibrate strobe the radio."""
62         self.strobe(0x02);
63     def CC_RFST(self,state=0x00):
64         self.strobe(state);
65         return;
66     def peek(self,reg,bytes=2):
67         """Read a CCSPI Register.  For long regs, result is flipped."""
68         
69         #Reg is ORed with 0x40 by the GoodFET.
70         data=[reg,0,0];
71         
72         #Automatically calibrate the len.
73         bytes=2;
74         
75         self.writecmd(self.CCSPIAPP,0x02,len(data),data);
76         toret=(
77             ord(self.data[2])+
78             (ord(self.data[1])<<8)
79             );
80         return toret;
81     def poke(self,reg,val,bytes=2):
82         """Write a CCSPI Register."""
83         data=[reg,(val>>8)&0xFF,val&0xFF];
84         self.writecmd(self.CCSPIAPP,0x03,len(data),data);
85         if self.peek(reg,bytes)!=val:
86             print "Warning, failed to set r%02x=0x%04x, got %02x." %(
87                 reg,
88                 val,
89                 self.peek(reg,bytes));
90         return;
91     
92     def status(self):
93         """Read the status byte."""
94         status=self.strobe(0x00);
95         print "Status=%02x" % status;
96     
97     #Radio stuff begins here.
98     def RF_setenc(self,code="802.15.4"):
99         """Set the encoding type."""
100         return;
101     def RF_getenc(self):
102         """Get the encoding type."""
103         return "802.15.4";
104     def RF_getrate(self):
105         return 0;
106     def RF_setrate(self,rate=0):
107         return 0;
108     def RF_setfreq(self,frequency):
109         """Set the frequency in Hz."""
110         mhz=frequency/1000000;
111         fsctrl=self.peek(0x18)&~0x3FF;
112         fsctrl=fsctrl+int(mhz-2048)
113         self.poke(0x18,fsctrl);
114     def RF_getfreq(self):
115         """Get the frequency in Hz."""
116         fsctrl=self.peek(0x18);
117         mhz=2048+(fsctrl&0x3ff)
118         return mhz*1000000;
119     def RF_getsmac(self):
120         """Return the source MAC address."""
121         return 0xdeadbeef;
122     def RF_setsmac(self,mac):
123         """Set the source MAC address."""
124         return 0xdeadbeef;
125     def RF_gettmac(self):
126         """Return the target MAC address."""
127         return 0xdeadbeef;
128     def RF_settmac(self,mac):
129         """Set the target MAC address."""
130         return 0xdeadbeef;
131     def RF_getrssi(self):
132         """Returns the received signal strenght, with a weird offset."""
133         rssival=self.peek(0x13)&0xFF; #raw RSSI register, should normalize this
134         return rssival^0x80;
135     lastpacket=range(0,0xff);
136     def RF_rxpacket(self):
137         """Get a packet from the radio.  Returns None if none is waiting.  In
138         order to not require the SFD, FIFO, or FIFOP lines, this
139         implementation works by comparing the buffer to the older
140         contents.
141         """
142         self.strobe(0x03); #SRXON
143         self.strobe(0x08); #SFLUSHRX
144         
145         buffer=range(0,0xff);
146         buffer[0]=0x3F | 0x40; #RXFIFO
147         buffer=self.trans(buffer);
148         
149         new=False;
150         for foo in range(2,20):
151             if buffer[foo]!=self.lastpacket[foo]:
152                 new=True;
153         if not new:
154             return None;
155         
156         
157         self.lastpacket=buffer;
158         return buffer;
159     def RF_carrier(self):
160         """Hold a carrier wave on the present frequency."""
161         print "Don't know how to hold a carrier.";
162     packetlen=16;
163     def RF_setpacketlen(self,len=16):
164         """Set the number of bytes in the expected payload."""
165         #self.poke(0x11,len);
166         self.packetlen=len;
167     def RF_getpacketlen(self):
168         """Set the number of bytes in the expected payload."""
169         #len=self.peek(0x11);
170         self.packetlen=len;
171         return len;
172     maclen=5;
173     def RF_getmaclen(self):
174         """Get the number of bytes in the MAC address."""
175         choices=[0, 3, 4, 5];
176         choice=self.peek(0x03)&3;
177         self.maclen=choices[choice];
178         return self.maclen;
179     def RF_setmaclen(self,len):
180         """Set the number of bytes in the MAC address."""
181         choices=["illegal", "illegal", "illegal", 
182                  1, 2, 3];
183         choice=choices[len];
184         self.poke(0x03,choice);
185         self.maclen=len;