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.strobe(0x02); #SCAL
23 self.poke(0x11, 0x0AC2); #MDMCTRL0
24 self.poke(0x12, 0x0500); #MDMCTRL1
25 self.poke(0x1C, 0x007F); #IOCFG0
26 self.poke(0x19, 0x01C4); #SECCTRL0, disabling crypto
29 return self.peek(0x1E); #MANFIDL
31 manfidl=self.peek(0x1E);
32 #manfidh=self.peek(0x1f);
34 return "%s" % (self.CCversions[manfidl]);
36 return "Unknown0x%04x" % manfidl;
37 def trans8(self,byte):
38 """Read and write 8 bits by CCSPI."""
39 data=self.CCSPItrans([byte]);
43 """Exchange data by CCSPI."""
45 self.writecmd(self.CCSPIAPP,0x00,len(data),data);
47 def strobe(self,reg=0x00):
48 """Strobes a strobe register, returning the status."""
51 return ord(self.data[0]);
52 def CC_RFST_IDLE(self):
53 """Switch the radio to idle mode, clearing overflows and errors."""
54 self.strobe(0x06); #SRXOFF
56 """Switch the radio to TX mode."""
57 self.strobe(0x04); #0x05 for CCA
59 """Switch the radio to RX mode."""
61 def CC_RFST_CAL(self):
62 """Calibrate strobe the radio."""
64 def CC_RFST(self,state=0x00):
67 def peek(self,reg,bytes=2):
68 """Read a CCSPI Register. For long regs, result is flipped."""
70 #Reg is ORed with 0x40 by the GoodFET.
73 #Automatically calibrate the len.
76 self.writecmd(self.CCSPIAPP,0x02,len(data),data);
79 (ord(self.data[1])<<8)
82 def poke(self,reg,val,bytes=2):
83 """Write a CCSPI Register."""
84 data=[reg,(val>>8)&0xFF,val&0xFF];
85 self.writecmd(self.CCSPIAPP,0x03,len(data),data);
86 if self.peek(reg,bytes)!=val:
87 print "Warning, failed to set r%02x=0x%04x, got %02x." %(
90 self.peek(reg,bytes));
94 """Read the status byte."""
95 statusbits={0x80: "?",
96 0x40: "XOSC16M_STABLE",
103 status=self.strobe(0x00);
108 str="%s %s" % (statusbits[i],str);
112 #Radio stuff begins here.
113 def RF_setenc(self,code="802.15.4"):
114 """Set the encoding type."""
117 """Get the encoding type."""
119 def RF_getrate(self):
121 def RF_setrate(self,rate=0):
123 def RF_setfreq(self,frequency):
124 """Set the frequency in Hz."""
125 mhz=frequency/1000000;
126 fsctrl=self.peek(0x18)&~0x3FF;
127 fsctrl=fsctrl+int(mhz-2048)
128 self.poke(0x18,fsctrl);
130 def RF_getfreq(self):
131 """Get the frequency in Hz."""
132 fsctrl=self.peek(0x18);
133 mhz=2048+(fsctrl&0x3ff)
135 def RF_getsmac(self):
136 """Return the source MAC address."""
138 def RF_setsmac(self,mac):
139 """Set the source MAC address."""
141 def RF_gettmac(self):
142 """Return the target MAC address."""
144 def RF_settmac(self,mac):
145 """Set the target MAC address."""
147 def RF_getrssi(self):
148 """Returns the received signal strenght, with a weird offset."""
149 rssival=self.peek(0x13)&0xFF; #raw RSSI register
151 lastpacket=range(0,0xff);
152 def RF_rxpacket(self):
153 """Get a packet from the radio. Returns None if none is waiting. In
154 order to not require the SFD, FIFO, or FIFOP lines, this
155 implementation works by comparing the buffer to the older
161 self.writecmd(self.CCSPIAPP,0x80,len(data),data);
164 self.lastpacket=buffer;
168 def RF_txpacket(self,packet):
169 """Send a packet through the radio."""
170 self.writecmd(self.CCSPIAPP,0x81,len(packet),packet);
175 def RF_carrier(self):
176 """Hold a carrier wave on the present frequency."""
177 print "Don't know how to hold a carrier.";
178 def RF_promiscuity(self,promiscuous=1):
179 mdmctrl0=self.peek(0x11);
180 #print "mdmctrl0 was %04x" % mdmctrl0;
181 mdmctrl0=mdmctrl0&(~0x800);
182 #print "mdmctrl0 is now %04x" % mdmctrl0;
183 self.poke(0x11,mdmctrl0);
187 def RF_setpacketlen(self,len=16):
188 """Set the number of bytes in the expected payload."""
189 #self.poke(0x11,len);
191 def RF_getpacketlen(self):
192 """Set the number of bytes in the expected payload."""
193 #len=self.peek(0x11);
197 def RF_getmaclen(self):
198 """Get the number of bytes in the MAC address."""
199 choices=[0, 3, 4, 5];
200 choice=self.peek(0x03)&3;
201 self.maclen=choices[choice];
203 def RF_setmaclen(self,len):
204 """Set the number of bytes in the MAC address."""
205 choices=["illegal", "illegal", "illegal",
208 self.poke(0x03,choice);