2 # GoodFET Chipcon RF Radio Client
4 # (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
6 # This code is being rewritten and refactored. You've been warned!
8 import sys, time, string, cStringIO, struct, glob, serial, os;
10 from GoodFET import GoodFET;
12 class GoodFETCCSPI(GoodFET):
14 CCversions={0x233d: "CC2420",
17 """Move the FET into the CCSPI application."""
18 self.writecmd(self.CCSPIAPP,0x10,0,self.data); #CCSPI/SETUP
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
28 return self.peek(0x1E); #MANFIDL
30 manfidl=self.peek(0x1E);
31 #manfidh=self.peek(0x1f);
33 return "%s" % (self.CCversions[manfidl]);
35 return "Unknown0x%04x" % manfidl;
36 def trans8(self,byte):
37 """Read and write 8 bits by CCSPI."""
38 data=self.CCSPItrans([byte]);
42 """Exchange data by CCSPI."""
44 self.writecmd(self.CCSPIAPP,0x00,len(data),data);
46 def strobe(self,reg=0x00):
47 """Strobes a strobe register, returning the status."""
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
55 """Switch the radio to TX mode."""
56 self.strobe(0x04); #0x05 for CCA
58 """Switch the radio to RX mode."""
60 def CC_RFST_CAL(self):
61 """Calibrate strobe the radio."""
63 def CC_RFST(self,state=0x00):
66 def peek(self,reg,bytes=2):
67 """Read a CCSPI Register. For long regs, result is flipped."""
69 #Reg is ORed with 0x40 by the GoodFET.
72 #Automatically calibrate the len.
75 self.writecmd(self.CCSPIAPP,0x02,len(data),data);
78 (ord(self.data[1])<<8)
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." %(
89 self.peek(reg,bytes));
93 """Read the status byte."""
94 statusbits={0x80: "?",
95 0x40: "XOSC16M_STABLE",
102 status=self.strobe(0x00);
107 str="%s %s" % (statusbits[i],str);
111 #Radio stuff begins here.
112 def RF_setenc(self,code="802.15.4"):
113 """Set the encoding type."""
116 """Get the encoding type."""
118 def RF_getrate(self):
120 def RF_setrate(self,rate=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)
133 def RF_getsmac(self):
134 """Return the source MAC address."""
136 def RF_setsmac(self,mac):
137 """Set the source MAC address."""
139 def RF_gettmac(self):
140 """Return the target MAC address."""
142 def RF_settmac(self,mac):
143 """Set the target MAC address."""
145 def RF_getrssi(self):
146 """Returns the received signal strenght, with a weird offset."""
147 rssival=self.peek(0x13)&0xFF; #raw RSSI register
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
157 # TODO -- Flush only if there's an overflow.
158 #self.strobe(0x08); #SFLUSHRX
162 self.writecmd(self.CCSPIAPP,0x80,len(data),data);
165 self.lastpacket=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
175 self.strobe(0x03); #SRXON
176 self.strobe(0x08); #SFLUSHRX
178 buffer=range(0,0xff);
179 buffer[0]=0x3F | 0x40; #RXFIFO
180 buffer=self.trans(buffer);
183 for foo in range(0,ord(buffer[0])):
184 if buffer[foo]!=self.lastpacket[foo]:
190 self.lastpacket=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);
204 def RF_setpacketlen(self,len=16):
205 """Set the number of bytes in the expected payload."""
206 #self.poke(0x11,len);
208 def RF_getpacketlen(self):
209 """Set the number of bytes in the expected payload."""
210 #len=self.peek(0x11);
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];
220 def RF_setmaclen(self,len):
221 """Set the number of bytes in the MAC address."""
222 choices=["illegal", "illegal", "illegal",
225 self.poke(0x03,choice);