Added basic firmware and client support for the zigduino/atmel128rfa1. It can now...
[goodfet] / client / GoodFETatmel128.py
diff --git a/client/GoodFETatmel128.py b/client/GoodFETatmel128.py
new file mode 100644 (file)
index 0000000..876725c
--- /dev/null
@@ -0,0 +1,222 @@
+# GoodFET client to interface zigduino/atmel128 radio
+# forked by bx from code by neighbor Travis Goodspeed
+from GoodFETAVR import GoodFETAVR
+import sys, binascii, os, array, time, glob, struct
+
+fmt = ("B", "<H", None, "<L")
+
+class GoodFETatmel128rfa1(GoodFETAVR):
+    ATMELRADIOAPP = 0x53
+    def pyserInit(self, port, timeout, attemptlimit):
+        """Open the serial port"""
+        # Make timeout None to wait forever, 0 for non-blocking mode.
+        import serial;
+
+        if os.name=='nt' and sys.version.find('64 bit')!=-1:
+            print "WARNING: PySerial requires a 32-bit Python build in Windows.";
+
+        if port is None and os.environ.get("GOODFET")!=None:
+            glob_list = glob.glob(os.environ.get("GOODFET"));
+            if len(glob_list) > 0:
+                port = glob_list[0];
+            else:
+                port = os.environ.get("GOODFET");
+        if port is None:
+            glob_list = glob.glob("/dev/tty.usbserial*");
+            if len(glob_list) > 0:
+                port = glob_list[0];
+        if port is None:
+            glob_list = glob.glob("/dev/ttyUSB*");
+            if len(glob_list) > 0:
+                port = glob_list[0];
+        if port is None:
+            glob_list = glob.glob("/dev/ttyU0");
+            if len(glob_list) > 0:
+                port = glob_list[0];
+        if port is None and os.name=='nt':
+            from scanwin32 import winScan;
+            scan=winScan();
+            for order,comport,desc,hwid in sorted(scan.comports()):
+                try:
+                    if hwid.index('FTDI')==0:
+                        port=comport;
+                        #print "Using FTDI port %s" % port
+                except:
+                    #Do nothing.
+                    a=1;
+
+        baud=115200;
+        self.serialport = serial.Serial(
+            port,
+            baud,
+            parity = serial.PARITY_NONE,
+            timeout=timeout
+            )
+
+        self.verb=0;
+        self.data=""
+        attempts=0;
+        connected=0;
+
+        while connected==0:
+            while self.verb!=0x7F or self.data!="http://goodfet.sf.net/":
+                if attemptlimit is not None and attempts >= attemptlimit:
+                    return
+                elif attempts==2 and os.environ.get("board")!='telosb':
+                    print "See the GoodFET FAQ about missing info flash.";
+                    self.serialport.setTimeout(0.2);
+                    #Explicitly set RTS and DTR to halt board.
+                    self.serialport.setRTS(1);
+                    self.serialport.setDTR(1);
+                    #Drop DTR, which is !RST, low to begin the app.
+                    self.serialport.setDTR(0);
+
+                attempts=attempts+1;
+                self.readcmd(); #Read the first command.
+                if self.verbose:
+                    print "Got %02x,%02x:'%s'" % (self.app,self.verb,self.data);
+
+            #Here we have a connection, but maybe not a good one.
+            #print "We have a connection."
+            for foo in range(1,30):
+                time.sleep(1)
+                if not self.monitorecho():
+                    connected = 0
+                    if self.verbose:
+                        print "Comm error on try %i." % (foo)
+                else:
+                    connected = 1
+                    break
+        if self.verbose:
+            print "Connected after %02i attempts." % attempts;
+        self.serialport.setTimeout(12);
+
+
+    def writecmd(self, app, verb, count=0, data=[]):
+        """Write a command and some data to the GoodFET."""
+        self.serialport.write(chr(app));
+        self.serialport.write(chr(verb));
+
+        if count > 0:
+            if(isinstance(data,list)):
+                old = data
+                data = []
+                for i in range(0,count):
+                    data += chr(old[i]);
+            outstr=''.join(data);
+
+        #little endian 16-bit length
+            count = len(outstr)
+            self.serialport.write(chr(count&0xFF));
+            self.serialport.write(chr(count>>8));
+            if self.verbose:
+                print "Tx: ( 0x%02x, 0x%02x, %d )" % ( app, verb, count )
+                print "sending: %s" %outstr.encode("hex")
+
+            self.serialport.write(outstr);
+        else: # count == 0
+            self.serialport.write("\x00")
+            self.serialport.write("\x00")
+
+        if not self.besilent:
+            out = self.readcmd()
+            #if out:
+            #    print "read: " + out
+            return out
+        else:
+            return []
+
+    def readcmd(self):
+        """Read a reply from the GoodFET."""
+        app = self.serialport.read(1)
+        if len(app) < 1:
+            self.app = 0
+            self.verb = 0
+            self.count = 0
+            self.data = ""
+            return
+
+        self.app=ord(app);
+        self.verb=ord(self.serialport.read(1));
+
+        self.count= ord(self.serialport.read(1)) + (ord(self.serialport.read(1))<<8)
+
+        if self.verbose:
+            print "Rx: ( 0x%02x, 0x%02x, %i )" % ( self.app, self.verb, self.count )
+
+        #Debugging string; print, but wait.
+        if self.app==0xFF:
+            if self.verb==0xFF:
+                print "# DEBUG %s" % self.serialport.read(self.count)
+            elif self.verb==0xFE:
+                print "# DEBUG 0x%x" % struct.unpack(fmt[self.count-1], self.serialport.read(self.count))[0]
+            elif self.verb==0xFD:
+                        #Do nothing, just wait so there's no timeout.
+                print "# NOP.";
+            return ""
+        else:
+            self.data=self.serialport.read(self.count);
+            return self.data;
+
+    def RF_setchannel(self, chan):
+        if (chan < 11) or (chan > 26):
+            print "Channel out of range"
+        else:
+            self.poke(0x8, chan)
+
+    def peek(self,reg,bytes=-1):
+        """Read a Register. """
+        #Automatically calibrate the len.
+        if bytes==-1:
+            bytes=1;
+            #if reg==0x0a or reg==0x0b or reg==0x10: bytes=5;
+        data = [reg, 0, bytes%255, bytes>>8] + ([0]*bytes)
+        self.writecmd(self.ATMELRADIOAPP,0x02,len(data),data);
+        toret=0;
+        #print self.data.encode("hex")
+        if self.data:
+            #for i in range(0,bytes):
+            #    toret=toret|(ord(self.data[i+1])<<(8*i));
+            #return toret;
+            # right now only works with a byte of data
+            return ord(self.data)
+        else:
+            return -1
+
+    def poke(self,reg,val,bytes=-1):
+        """Write an Register."""
+        data=[reg, 0]
+
+        #Automatically calibrate the len.
+        if bytes==-1:
+            bytes=1;
+            #if reg==0x0a or reg==0x0b or reg==0x10: bytes=5;
+        for i in range(0,bytes):
+            data=data+[(val>>(8*i))&0xFF];
+
+        self.writecmd(self.ATMELRADIOAPP,0x03,len(data),data);
+        if self.peek(reg,bytes)!=val:
+            print "Warning, failed to set r%02x=%02x, got %02x." %(
+                reg,
+                val,
+                self.peek(reg,bytes));
+
+        return;
+
+
+    def RF_setup(self):
+        self.writecmd(self.ATMELRADIOAPP, 0x10, 0, None)
+
+    def RF_rxpacket(self):
+        """Get a packet from the radio.  Returns None if none is waiting."""
+        #doto: check if packet has arrived, flush if not new
+        self.writecmd(self.ATMELRADIOAPP, 0x80, 0, None)
+        data=self.data;
+        self.packetlen = len(data)
+        if (self.packetlen > 0):
+            return data;
+        else:
+            return None
+
+    def RX_txpacket(self, payload):
+        self.writecmd(self.ATMELRADIOAPP, 0x81, len(payload)+1,chr(len(payload))+payload)