612ce3e685ca2f4bb2f9c0ae2946db9114179e06
[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
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         
143         # TODO -- Flush only if there's an overflow.
144         #self.strobe(0x08); #SFLUSHRX
145         
146         data="\0";
147         self.data=data;
148         self.writecmd(self.CCSPIAPP,0x80,len(data),data);
149         buffer=self.data;
150         
151         self.lastpacket=buffer;
152         if(len(buffer)==0):
153             return None;
154         return buffer;
155     def RF_rxpacket_old(self):
156         """Get a packet from the radio.  Returns None if none is waiting.  In
157         order to not require the SFD, FIFO, or FIFOP lines, this
158         implementation works by comparing the buffer to the older
159         contents.
160         """
161         self.strobe(0x03); #SRXON
162         self.strobe(0x08); #SFLUSHRX
163         
164         buffer=range(0,0xff);
165         buffer[0]=0x3F | 0x40; #RXFIFO
166         buffer=self.trans(buffer);
167         
168         new=False;
169         for foo in range(0,ord(buffer[0])):
170             if buffer[foo]!=self.lastpacket[foo]:
171                 new=True;
172         if not new:
173             return None;
174         
175         
176         self.lastpacket=buffer;
177         return buffer;
178     def RF_carrier(self):
179         """Hold a carrier wave on the present frequency."""
180         print "Don't know how to hold a carrier.";
181     def RF_promiscuity(self,promiscuous=1):
182         mdmctrl0=self.peek(0x11);
183         print "mdmctrl0 was %04x" % mdmctrl0;
184         mdmctrl0=mdmctrl0&(~0x800);
185         print "mdmctrl0 is now %04x" % mdmctrl0;
186         self.poke(0x11,mdmctrl0);
187         return;
188         
189     packetlen=16;
190     def RF_setpacketlen(self,len=16):
191         """Set the number of bytes in the expected payload."""
192         #self.poke(0x11,len);
193         self.packetlen=len;
194     def RF_getpacketlen(self):
195         """Set the number of bytes in the expected payload."""
196         #len=self.peek(0x11);
197         self.packetlen=len;
198         return len;
199     maclen=5;
200     def RF_getmaclen(self):
201         """Get the number of bytes in the MAC address."""
202         choices=[0, 3, 4, 5];
203         choice=self.peek(0x03)&3;
204         self.maclen=choices[choice];
205         return self.maclen;
206     def RF_setmaclen(self,len):
207         """Set the number of bytes in the MAC address."""
208         choices=["illegal", "illegal", "illegal", 
209                  1, 2, 3];
210         choice=choices[len];
211         self.poke(0x03,choice);
212         self.maclen=len;