1 # GoodFETclient to interface zigduino/atmel128 radio
2 # forked by bx from code by neighbor Travis Goodspeed
3 from GoodFETAVR import GoodFETAVR
4 import sys, binascii, os, array, time, glob, struct
6 fmt = ("B", "<H", None, "<L")
8 class GoodFETatmel128rfa1(GoodFETAVR):
14 def serInit(self, port=None, timeout=2, attemptlimit=None):
16 port=os.environ.get("GOODFET");
17 self.pyserInit(port, timeout, attemptlimit)
19 def pyserInit(self, port, timeout, attemptlimit):
20 """Open the serial port"""
21 if self.connected == 0:
22 if (not (attemptlimit == None)) and (attemptlimit <= 1):
23 # it always takes at least 2 tries
26 # Make timeout None to wait forever, 0 for non-blocking mode.
29 if os.name=='nt' and sys.version.find('64 bit')!=-1:
30 print "WARNING: PySerial requires a 32-bit Python build in Windows.";
32 if port is None and os.environ.get("GOODFET")!=None:
33 glob_list = glob.glob(os.environ.get("GOODFET"));
34 if len(glob_list) > 0:
37 port = os.environ.get("GOODFET");
39 glob_list = glob.glob("/dev/tty.usbserial*");
40 if len(glob_list) > 0:
43 glob_list = glob.glob("/dev/ttyUSB*");
44 if len(glob_list) > 0:
47 glob_list = glob.glob("/dev/ttyU0");
48 if len(glob_list) > 0:
50 if port is None and os.name=='nt':
51 from scanwin32 import winScan;
53 for order,comport,desc,hwid in sorted(scan.comports()):
55 if hwid.index('FTDI')==0:
57 #print "Using FTDI port %s" % port
64 self.serialport = serial.Serial(
67 parity = serial.PARITY_NONE,
76 while self.connected==0:
77 self.serialport.setDTR(False)
78 while self.verb!=0x7F or self.data!="http://goodfet.sf.net/":
79 if attemptlimit is not None and attempts >= attemptlimit:
83 self.readcmd(); #Read the first command.
85 print "Got %02x,%02x:'%s'" % (self.app,self.verb,self.data);
87 #Here we have a connection, but maybe not a good one.
88 #print "We have a connection."
89 for foo in range(1,30):
91 if not self.monitorecho():
94 print "Comm error on try %i." % (foo)
99 print "Connected after %02i attempts." % attempts;
100 self.serialport.setTimeout(12);
104 self.serialport.close()
107 def writecmd(self, app, verb, count=0, data=[]):
108 """Write a command and some data to the GoodFET."""
109 self.serialport.write(chr(app));
110 self.serialport.write(chr(verb));
112 print "Tx: ( 0x%02x, 0x%02x, %d )" % ( app, verb, count )
114 if(isinstance(data,list)):
117 for i in range(0,count):
119 outstr=''.join(data);
121 #little endian 16-bit length
123 self.serialport.write(chr(count&0xFF));
124 self.serialport.write(chr(count>>8));
127 print "sending: %s" %outstr.encode("hex")
128 self.serialport.write(outstr);
131 if not self.besilent:
133 if out and self.verbose:
134 print "read: " + out.encode("hex")
141 """Read a reply from the GoodFET."""
142 app = self.serialport.read(1)
156 v = self.serialport.read(1);
162 c1 = self.serialport.read(1)
163 c2 = self.serialport.read(1)
165 self.count= ord(c1) + (ord(c2)<<8)
169 print "Rx: ( 0x%02x, 0x%02x, %i )" % ( self.app, self.verb, self.count )
171 #Debugging string; print, but wait.
174 print "# DEBUG %s" % self.serialport.read(self.count)
175 elif self.verb==0xFE:
176 print "# DEBUG 0x%x" % struct.unpack(fmt[self.count-1], self.serialport.read(self.count))[0]
177 elif self.verb==0xFD:
178 #Do nothing, just wait so there's no timeout.
182 self.data=self.serialport.read(self.count);
185 def RF_setchannel(self, chan):
186 if (chan < 11) or (chan > 26):
187 print "Channel out of range"
191 def peek(self,reg,bytes=1):
192 """Read a Register. """
193 #Automatically calibrate the len.
195 print "Warning, currently cannot poke more than 1 byte"
197 data = [reg, 0, bytes%255, bytes>>8] #+ ([0]*bytes)
199 self.writecmd(self.ATMELRADIOAPP,0x02,len(data),data);
201 #print self.data.encode("hex")
203 #for i in range(0,bytes):
204 # toret=toret|(ord(self.data[i+1])<<(8*i));
206 # right now only works with a byte of data
207 return ord(self.data)
211 def poke(self,reg,val,bytes=1): # todo, support >1 byte
212 """Write an Register."""
213 data = [reg, 0] #+ ([0]*bytes)
216 print "Warning, currently cannot poke more than 1 byte"
218 for i in range(0,bytes):
219 data=data+[(val>>(8*i))&0xFF];
221 self.writecmd(self.ATMELRADIOAPP,0x03,len(data),data);
222 newval = self.peek(reg,bytes)
224 print "Warning, failed to set r%02x=%02x, got %02x." %(
235 self.writecmd(self.ATMELRADIOAPP, 0x10, 0, None)
237 def RF_rxpacket(self):
238 """Get a packet from the radio. Returns None if none is waiting."""
239 #doto: check if packet has arrived, flush if not new
240 self.writecmd(self.ATMELRADIOAPP, 0x80, 0, None)
242 self.packetlen = len(data)
243 if (self.packetlen > 0):
248 def RF_txpacket(self, payload):
249 if type(payload) == list: #convert to string
251 payload = array.array('B', payload).tostring()
252 self.writecmd(self.ATMELRADIOAPP, 0x81, len(payload), payload)
255 def RF_getrssi(self):
256 """Returns the received signal strength"""
258 val = self.peek(0x7) & 0x7f # read rssi bits
266 def RF_enable_AACK(self, enable = True):
267 if (enable and (not self.enable_AACK)):
268 self.enable_AACK = True
269 self.writecmd(self.ATMELRADIOAPP, 0x84)
270 elif ((not enable) and self.enable_AACK):
271 self.enable_AACK = False
272 self.writecmd(self.ATMELRADIOAPP, 0x85)
275 def RF_autocrc(self, autocrc=1):
276 self.autocrc = autocrc
278 self.writecmd(self.ATMELRADIOAPP, 0x86)
280 self.writecmd(self.ATMELRADIOAPP, 0x87)