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 status=self.strobe(0x00);
95 print "Status=%02x" % status;
97 #Radio stuff begins here.
98 def RF_setenc(self,code="802.15.4"):
99 """Set the encoding type."""
102 """Get the encoding type."""
104 def RF_getrate(self):
106 def RF_setrate(self,rate=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)
119 def RF_getsmac(self):
120 """Return the source MAC address."""
122 def RF_setsmac(self,mac):
123 """Set the source MAC address."""
125 def RF_gettmac(self):
126 """Return the target MAC address."""
128 def RF_settmac(self,mac):
129 """Set the target MAC address."""
131 def RF_getrssi(self):
132 """Returns the received signal strenght, with a weird offset."""
133 rssival=self.peek(0x13)&0xFF; #raw RSSI register
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
143 # TODO -- Flush only if there's an overflow.
144 #self.strobe(0x08); #SFLUSHRX
148 self.writecmd(self.CCSPIAPP,0x80,len(data),data);
151 self.lastpacket=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
161 self.strobe(0x03); #SRXON
162 self.strobe(0x08); #SFLUSHRX
164 buffer=range(0,0xff);
165 buffer[0]=0x3F | 0x40; #RXFIFO
166 buffer=self.trans(buffer);
169 for foo in range(0,ord(buffer[0])):
170 if buffer[foo]!=self.lastpacket[foo]:
176 self.lastpacket=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);
190 def RF_setpacketlen(self,len=16):
191 """Set the number of bytes in the expected payload."""
192 #self.poke(0x11,len);
194 def RF_getpacketlen(self):
195 """Set the number of bytes in the expected payload."""
196 #len=self.peek(0x11);
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];
206 def RF_setmaclen(self,len):
207 """Set the number of bytes in the MAC address."""
208 choices=["illegal", "illegal", "illegal",
211 self.poke(0x03,choice);