3 from spec
.pinfunctions
import pinspec
4 from copy
import deepcopy
7 def namesuffix(name
, suffix
, namelist
):
11 names
.append("%s%s_%s" % (name
, suffix
, n
))
13 names
.append("%s_%s" % (name
, suffix
))
18 """ a meta-helper which creates pins from the pinspec
19 and adds them to the pinouts.
21 __call__ is used to effectively create a lambda function, which
22 in combination with setattr (below) gives the function a name
23 in the Pinouts class, according to the pinspec.
25 arguments to __call__ (which ends up as Pinouts.i2s, Pinouts.sdmmc
26 and so on, according to spec.pinfunctions.pinspec) are:
28 suffix: e.g. GPIO or SD or SPI
29 offs : a tuple of (Bank, Bank offset) as a string, integer
30 mux : which column in the multiplexer
31 start : the start of a subset of pins to be inserted
32 limit : the end of the subset (or the number if start also given)
33 spec : *EXTRA* pins to be inserted (at different implicit positions)
35 the pins are inserted with the suffix, starting from the
36 offset position using offs as the row and mux as the column,
37 and working in a constant increment down the rows.
39 spec is slightly complicated, basically there's extra
40 functions that we want to be on the same pin (but a different mux)
41 because their use is mutually-exclusive. without this spec
42 argument the extra pins would need to be MANUALLY moved about
43 during the development of the pinmux, if the "main" pins
44 were also moved about. this would be a pain.
46 so instead, extra pins are given of the form:
47 { 'EXTRA1' : ('PREEXISTING_NAME', MUX_COLUMN),
51 where the function EXTRA1 will always be placed on the SAME ROW
52 as PREEXISTING_NAME, just in MUX_COLUMN. this may be done
53 several times i.e. multiple new EXTRA functions can be added
54 on the same row as PRE_EXISTING_NAME, just with different
57 Note: spec must implicitly be in the same Bank.
60 def __init__(self
, pinouts
, fname
, pinfn
, bankspec
):
61 self
.pinouts
= pinouts
62 self
.bankspec
= bankspec
66 def __call__(self
, suffix
, offs
, mux
,
67 start
=None, limit
=None, spec
=None, origsuffix
=None):
69 pingroup
, gangedgroup
= self
.pinfn(suffix
, bank
)
70 if isinstance(pingroup
, tuple):
71 prefix
, pingroup
= pingroup
74 if start
and limit
: # limit turns into an offset from start
76 pingroup
= pingroup
[start
:limit
] # see comment in spec.pinfunctions
77 pins
= Pins(prefix
, pingroup
, self
.bankspec
,
78 suffix
, offs
, bank
, mux
,
79 spec
, origsuffix
=suffix
, gangedgrp
=gangedgroup
)
80 fname
= self
.pinouts
.pinmerge(pins
)
81 self
.pinouts
.setganged(fname
, gangedgroup
)
86 class Pinouts(object):
87 def __init__(self
, bankspec
):
88 self
.bankspec
= bankspec
92 for fname
, pinfn
in pinspec
:
93 if isinstance(pinfn
, tuple):
97 setattr(self
, name
, PinGen(self
, fname
, pinfn
, self
.bankspec
))
99 def setganged(self
, fname
, grp
):
100 grp
= map(lambda x
: x
[:-1], grp
)
101 if fname
not in self
.ganged
:
102 self
.ganged
[fname
] = []
103 self
.ganged
[fname
] += grp
105 def __contains__(self
, k
):
106 return k
in self
.pins
108 def has_key(self
, k
):
109 return k
in self
.pins
111 def add_spec(self
, k
, v
):
114 def update(self
, pinidx
, v
):
115 if pinidx
not in self
.pins
:
116 self
.pins
[pinidx
] = v
119 assert k
not in self
.pins
[pinidx
], \
120 "pin %d position %d already taken\n%s\n%s" % \
121 (pinidx
, k
, str(v
), self
.pins
[pinidx
])
122 self
.pins
[pinidx
].update(v
)
125 return self
.pins
.keys()
128 return self
.pins
.items()
134 return len(self
.pins
)
136 def __delitem__(self
, k
):
139 def __getitem__(self
, k
):
142 def pinmerge(self
, fn
):
143 # hack, store the function specs in the pins dict
145 suffix
= fn
.origsuffix
148 if not hasattr(self
, 'fnspec'):
152 assert 'EINT' not in self
153 if fname
not in self
.fnspec
:
154 self
.add_spec(fname
, {})
155 if suffix
or fname
== 'EINT' or fname
== 'PWM':
156 specname
= fname
+ suffix
159 # print "fname bank specname suffix ", fname, bank, specname, repr(
161 if specname
in self
.fnspec
[fname
]:
162 # ok so some declarations may bring in different
163 # names at different stages (EINT, PWM, flexbus1/2)
164 # so we have to merge the names in. main thing is
166 tomerge
= self
.fnspec
[fname
][specname
]
167 for p
in fn
.pingroup
:
168 if p
not in tomerge
.pingroup
:
169 tomerge
.pingroup
.append(p
)
170 tomerge
.pins
.update(fn
.pins
)
171 tomerge
.fntype
.update(fn
.fntype
)
173 self
.fnspec
[fname
][specname
] = deepcopy(fn
)
176 for (pinidx
, v
) in fn
.pins
.items():
177 self
.update(pinidx
, v
)
184 def __init__(self
, fname
, pingroup
, bankspec
, suffix
, offs
, bank
, mux
,
185 spec
=None, limit
=None, origsuffix
=None, gangedgrp
=None):
187 # function type can be in, out or inout, represented by - + *
188 # strip function type out of each pin name
190 for i
in range(len(pingroup
)):
195 if fntype
not in '+-*':
198 fntype
= {'-': 'in', '+': 'out', '*': 'inout'}[fntype
]
199 self
.fntype
[pname
] = fntype
203 self
.pingroup
= pingroup
204 self
.gangedgroup
= gangedgrp
205 self
.bankspec
= bankspec
207 self
.origsuffix
= origsuffix
or suffix
211 # create consistent name suffixes
212 pingroup
= namesuffix(fname
, suffix
, pingroup
)
218 for name
in pingroup
[:limit
]:
220 name_
= "%s_%s" % (name
, suffix
)
223 if spec
and name
in spec
:
225 pin
= {mux
: (name_
, bank
)}
226 offs_bank
, offs_
= offs
229 idx_
+= bankspec
[bank
]
232 for name
in pingroup
:
234 name_
= "%s_%s" % (name
, suffix
)
241 idx_
, mux_
= spec
[name
]
243 pin
= {mux_
: (name_
, bank
)}
245 res
[idx_
].update(pin
)