Removed unnecessary register prints in RF_promiscuity of CCSPI.
[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         statusbits={0x80: "?",
95                     0x40: "XOSC16M_STABLE",
96                     0x20: "TX_UNDERFLOW",
97                     0x10: "ENC_BUSY",
98                     0x08: "TX_ACTIVE",
99                     0x04: "LOCK",
100                     0x02: "RSSI_VALID",
101                     0x01: "?"};
102         status=self.strobe(0x00);
103         i=1;
104         str="";
105         while i<0x100:
106             if status&i:
107                str="%s %s" % (statusbits[i],str);
108             i*=2;
109         return str;
110     
111     #Radio stuff begins here.
112     def RF_setenc(self,code="802.15.4"):
113         """Set the encoding type."""
114         return;
115     def RF_getenc(self):
116         """Get the encoding type."""
117         return "802.15.4";
118     def RF_getrate(self):
119         return 0;
120     def RF_setrate(self,rate=0):
121         return 0;
122     def RF_setfreq(self,frequency):
123         """Set the frequency in Hz."""
124         mhz=frequency/1000000;
125         fsctrl=self.peek(0x18)&~0x3FF;
126         fsctrl=fsctrl+int(mhz-2048)
127         self.poke(0x18,fsctrl);
128     def RF_getfreq(self):
129         """Get the frequency in Hz."""
130         fsctrl=self.peek(0x18);
131         mhz=2048+(fsctrl&0x3ff)
132         return mhz*1000000;
133     def RF_getsmac(self):
134         """Return the source MAC address."""
135         return 0xdeadbeef;
136     def RF_setsmac(self,mac):
137         """Set the source MAC address."""
138         return 0xdeadbeef;
139     def RF_gettmac(self):
140         """Return the target MAC address."""
141         return 0xdeadbeef;
142     def RF_settmac(self,mac):
143         """Set the target MAC address."""
144         return 0xdeadbeef;
145     def RF_getrssi(self):
146         """Returns the received signal strenght, with a weird offset."""
147         rssival=self.peek(0x13)&0xFF; #raw RSSI register
148         return rssival^0x80;
149     lastpacket=range(0,0xff);
150     def RF_rxpacket(self):
151         """Get a packet from the radio.  Returns None if none is waiting.  In
152         order to not require the SFD, FIFO, or FIFOP lines, this
153         implementation works by comparing the buffer to the older
154         contents.
155         """
156         
157         # TODO -- Flush only if there's an overflow.
158         #self.strobe(0x08); #SFLUSHRX
159         
160         data="\0";
161         self.data=data;
162         self.writecmd(self.CCSPIAPP,0x80,len(data),data);
163         buffer=self.data;
164         
165         self.lastpacket=buffer;
166         if(len(buffer)==0):
167             return None;
168         return buffer;
169     def RF_rxpacket_old(self):
170         """Get a packet from the radio.  Returns None if none is waiting.  In
171         order to not require the SFD, FIFO, or FIFOP lines, this
172         implementation works by comparing the buffer to the older
173         contents.
174         """
175         self.strobe(0x03); #SRXON
176         self.strobe(0x08); #SFLUSHRX
177         
178         buffer=range(0,0xff);
179         buffer[0]=0x3F | 0x40; #RXFIFO
180         buffer=self.trans(buffer);
181         
182         new=False;
183         for foo in range(0,ord(buffer[0])):
184             if buffer[foo]!=self.lastpacket[foo]:
185                 new=True;
186         if not new:
187             return None;
188         
189         
190         self.lastpacket=buffer;
191         return buffer;
192     def RF_carrier(self):
193         """Hold a carrier wave on the present frequency."""
194         print "Don't know how to hold a carrier.";
195     def RF_promiscuity(self,promiscuous=1):
196         mdmctrl0=self.peek(0x11);
197         #print "mdmctrl0 was %04x" % mdmctrl0;
198         mdmctrl0=mdmctrl0&(~0x800);
199         #print "mdmctrl0 is now %04x" % mdmctrl0;
200         self.poke(0x11,mdmctrl0);
201         return;
202         
203     packetlen=16;
204     def RF_setpacketlen(self,len=16):
205         """Set the number of bytes in the expected payload."""
206         #self.poke(0x11,len);
207         self.packetlen=len;
208     def RF_getpacketlen(self):
209         """Set the number of bytes in the expected payload."""
210         #len=self.peek(0x11);
211         self.packetlen=len;
212         return len;
213     maclen=5;
214     def RF_getmaclen(self):
215         """Get the number of bytes in the MAC address."""
216         choices=[0, 3, 4, 5];
217         choice=self.peek(0x03)&3;
218         self.maclen=choices[choice];
219         return self.maclen;
220     def RF_setmaclen(self,len):
221         """Set the number of bytes in the MAC address."""
222         choices=["illegal", "illegal", "illegal", 
223                  1, 2, 3];
224         choice=choices[len];
225         self.poke(0x03,choice);
226         self.maclen=len;