2 # GoodFET EM260 Radio Client
4 # (C) 2010 Travis Goodspeed <travis at radiantmachines.com>
6 # This code is being rewritten and refactored. You've been warned!
8 # The EM260 is almost textbook SPI, except that the response cannot be
9 # read until after the nHOST_INT pin of the EM260 drops low and a dummy
10 # byte is read. That is, the sequence will look like the following:
12 # Transmit Host->Slave Data
13 # while(nHOST_INT); //Sleep until ready.
15 # Recv Slave->Host Data
17 # The delay is mandatory.
19 import sys, time, string, cStringIO, struct, glob, os;
21 from GoodFETSPI import GoodFETSPI;
23 class GoodFETEM260(GoodFETSPI):
26 def EM260trans(self,data,retry=1):
27 """Exchange data by EM260 SPI. (Slightly nonstandard.)"""
30 #Retries exceeded. Send a trivial command to clear error.
32 self.writecmd(0x01,0x82,len(data),data);
36 reply=ord(self.data[0]);
38 #print "Warning: EM260 rebooted.";
39 return self.EM260trans(data,retry-1);
41 #print "Error: Aborted Transaction.";
42 return self.EM260trans(data,retry-1);
44 print "Error: Missing Frame Terminator.";
47 print "Error: Reserved Error. (Access denied?)";
50 print "Error in EM260trans.";
53 def EZSPtrans(self,frame):
54 """Send an EZSP frame."""
55 data=self.EM260trans([0xFE,len(frame)+2,
61 s=s+"%02x " % ord(foo);
64 if ord(data[0])!=0xFE:
65 print "EZSP error: 0x%02x" % ord(data[0]);
66 if ord(data[4])==0x58:
67 print "EZSP Invalid Command because 0x%02x" % ord(data[5]);
69 if frame[0]!=ord(data[4]):
70 print "EZSP warning: Command 0x%02x returned type 0x%02x." % (
71 frame[0],ord(data[4]));
76 """Read a byte from the given address. Untested."""
78 data=self.EZSPtrans([0x47,adr&0xFF,10]);
81 def poke8(self,adr,val):
82 """Poke a value into RAM. Untested"""
83 self.EZSPtrans([0x46,adr&0xFF,1,val&0xFF]);
86 """Read a random 16-bit word."""
88 data=self.EZSPtrans([0x49]);
90 print "Insufficient random data.";
92 return ord(data[6])+(ord(data[7])<<8);
95 """Read the info bytes."""
96 print "Ember EM26 Z-Stack SPI Module.";
97 version=self.EM260spiversion();
98 status=self.EM260spistatus();
99 print "Version: %i" % (version);
100 print "Status: %s" % (["dead","alive"][status]);
103 print "Node ID: %04x" % (self.getNodeID());
104 print "Connected to %2i neighbors." % self.neighborCount();
105 def EM260spiversion(self):
106 """Read the SPI version number from EM260."""
107 data=self.EM260trans([0x0A,0xA7]);
108 version=ord(data[0]);
111 return self.EM260spiversion();
113 return self.EM260spiversion();
115 print "Version misread.";
119 def EM260spistatus(self):
120 """Read the status bit."""
121 data=self.EM260trans([0x0B,0xA7]);
125 return self.EM260spistatus();
127 return self.EM260spistatus();
128 if not status&0x80 and status&0x40:
129 print "Status misread.";
133 #Everything after here is ZigBee.
136 """Read the EZSP node id."""
138 data=self.EZSPtrans([0x27]);
139 return ord(data[5])+(ord(data[6])<<8);
140 def neighborCount(self):
141 """Read the count of neighbors, used for iterating the neighbor table."""
143 data=self.EZSPtrans([0x7A]);
145 def setRadioChannel(self,channel):
146 """Set the radio channel."""
148 data=self.EZSPtrans([0x9A, channel&xFF]);
150 def setVersion(self,version=2):
151 """Set the requested EZSP protocol version."""
153 data=self.EZSPtrans([0x00, version]);
154 newversion=ord(data[5]);
155 if version==newversion:
157 print "Protocol %i, stack type %i, Stack Version 0x%02x%02x." % (
163 self.setVersion(newversion);