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