1 """
2 File: wixelTDMA
3
4 Implement TDMA interface via wixel boards
5 """
6
7 from numpy import zeros
8 from copy import deepcopy
9 from multiprotocol import MultiProtocol
10 from port2port import Connection, newConnection
11 from struct import pack, unpack
12
13 DEFAULT_WIXEL_PORT = dict(
14 TYPE='tty',
15 glob='/dev/ttyACM*',
16 baudrate=115200
17 )
18
20
21
22 tasks = deepcopy(list(tasks))
23
24 tasks[0].append(0)
25 slotNum = 0
26
27
28 for i in xrange(1, len(tasks)):
29
30
31 taskSlotAssigned = False
32
33
34 while not taskSlotAssigned:
35
36
37 slotBusy = False
38
39
40 for j in xrange(0,i):
41
42 if ((slotNum - tasks[j][3]) % tasks[j][1]) < tasks[j][2]:
43
44
45
46 slotBusy = True
47 newSlotNum = slotNum + tasks[j][2] - (slotNum - tasks[j][3])%tasks[j][1]
48
49
50
51
52 slotNum = newSlotNum
53
54
55 if not slotBusy:
56
57
58 taskSlotAssigned = True
59 tasks[i].append(slotNum)
60
61 break
62
63
64
65
66
67
68 periodDuration = 0
69 for i in xrange(0,len(tasks)):
70 if tasks[i][1] > periodDuration:
71
72 periodDuration = tasks[i][1]
73
74 period = zeros([1,periodDuration]).tolist()[0]
75
76
77
78 for i in xrange(0,len(tasks)):
79 for j in xrange(tasks[i][3], periodDuration, tasks[i][1]):
80 for k in xrange(0, tasks[i][2]):
81 if (period[j+k]):
82 print '\nCollision!'
83 period[j+k] = 'xxx'
84 period[j+k] = tasks[i][0]
85
86 pkt = [255]
87
88 for task in tasks:
89 start = task[3]
90 duration = task[2]
91 timePeriod = task[1]
92 pkt.extend([start,duration,timePeriod])
93
94 return pkt
95
97 """
98 Concrete Connction subclass specialized to send and recieve dat via
99 a specific TMDA node
100
101 ALGORITHM:
102 write -- prepend prefix and send via hub
103 read -- pull from message queue
104 """
105 - def __init__(self, hubwrite, hubisopen ):
106 self.isOpen = hubisopen
107 self.write = hubwrite
108 self.q = []
109
111 """Make the connection active"""
112 pass
113
116
117 - def read( self, length ):
118 if not self.q:
119 return None
120 return self.q.pop(0)[:length]
121
123 """Disconnect; further traffic may raise an exception
124 """
125 pass
126
128 """Try to reconnect with some configuration changes"""
129 raise IOError('Cannot reconnect TDMA Nodes')
130
131 -class Hub( MultiProtocol ):
132 """
133 Concrete MultiProtocol subclass for Wixel TDMA connections
134
135 TYPICAL USAGE:
136 H = Hub()
137 P1 = Dynamixel.Protocol( Dynamixel.Bus(
138 port = H.getNewNodeConnection( tid1 )
139 ))
140 H.addSubProtocol( P1 )
141 P2 = Dynamixel.Protocol( Dynamixel.Bus(
142 port = H.getNewNodeConnection( tid2 )
143 ))
144 H.addSubProtocol( P2 )
145 # start loop with H.update() called
146 """
148 """
149 INPUT:
150 """
151 MultiProtocol.__init__(self,*argv,**kw)
152
153
154
155 if wixelPort is None:
156 wixelPort = newConnection(DEFAULT_WIXEL_PORT)
157 elif type(wixelPort) in [dict,str]:
158 wixelPort = newConnection(wixelPort)
159 elif assert isinstance(wixelPort,Connection)
160 self.wix = wixelPort
161
162 self.tdn = {}
163
164 self.tp = []
165
167 """
168 INPUT:
169 tid -- TDMA node ID
170 OUTPUT:
171 a NodeConnection instance that sends data via that node
172 This is registered in self.tdn
173 """
174 assert not self.tdn.has_key(tid), "TMDA node ID can only be initialized once"
175 pfx = pack('B',tid)
176 nc = NodeConnection(
177 hubwrite = lambda msg : self.wix.write( pfx + msg ),
178 hubisopen = self.wix.isOpen
179 )
180 self.tdn[tid] = nc
181 return nc
182
184 """
185 (private) scan incoming messages and demultiplex them into
186 the respective NodeConnection queues
187 """
188 """
189 Using a buffer, reassemble messages from the wixel
190 once a complete message is received, find which tdn it belongs
191 to and queue it there. If an unknown tdn, record as error
192 also detect any bad framing of data from wixel
193 (note: wixel receives framed messages from HW)
194 """
195 pass
196
198 """Update all sub-protocols and collect heartbeats"""
199 hb = {}
200
201 for p in self.nim.iterowners():
202 p.update()
203
204 for inid,val in p.heartbeats.iteritems():
205 xnid = self.nim.mapI2X(p,inid)
206 hb[xnid] = val
207 self.heartbeats = hb
208 """!!!
209 if enough time has passed, self._emitTimeplan()
210 """
211 return self._demuxIncoming()
212
214 """(private) emit timeplan, generating a default one of needed"""
215 """
216 if self.tp is empty, give a generic slot to each node
217 otherwise use the self.tp to generate timeplan packet(s)
218 and send them
219 """
220 pass
221