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 self
.ganged
[fname
] = map(lambda x
: x
[:-1], grp
)
102 def __contains__(self
, k
):
103 return k
in self
.pins
105 def has_key(self
, k
):
106 return k
in self
.pins
108 def add_spec(self
, k
, v
):
111 def update(self
, pinidx
, v
):
112 if pinidx
not in self
.pins
:
113 self
.pins
[pinidx
] = v
116 assert k
not in self
.pins
[pinidx
], \
117 "pin %d position %d already taken\n%s\n%s" % \
118 (pinidx
, k
, str(v
), self
.pins
[pinidx
])
119 self
.pins
[pinidx
].update(v
)
122 return self
.pins
.keys()
125 return self
.pins
.items()
131 return len(self
.pins
)
133 def __delitem__(self
, k
):
136 def __getitem__(self
, k
):
139 def pinmerge(self
, fn
):
140 # hack, store the function specs in the pins dict
142 suffix
= fn
.origsuffix
145 if not hasattr(self
, 'fnspec'):
149 assert 'EINT' not in self
150 if fname
not in self
.fnspec
:
151 self
.add_spec(fname
, {})
152 if suffix
or fname
== 'EINT' or fname
== 'PWM':
153 specname
= fname
+ suffix
156 # print "fname bank specname suffix ", fname, bank, specname, repr(
158 if specname
in self
.fnspec
[fname
]:
159 # ok so some declarations may bring in different
160 # names at different stages (EINT, PWM, flexbus1/2)
161 # so we have to merge the names in. main thing is
163 tomerge
= self
.fnspec
[fname
][specname
]
164 for p
in fn
.pingroup
:
165 if p
not in tomerge
.pingroup
:
166 tomerge
.pingroup
.append(p
)
167 tomerge
.pins
.update(fn
.pins
)
168 tomerge
.fntype
.update(fn
.fntype
)
170 self
.fnspec
[fname
][specname
] = deepcopy(fn
)
173 for (pinidx
, v
) in fn
.pins
.items():
174 self
.update(pinidx
, v
)
181 def __init__(self
, fname
, pingroup
, bankspec
, suffix
, offs
, bank
, mux
,
182 spec
=None, limit
=None, origsuffix
=None, gangedgrp
=None):
184 # function type can be in, out or inout, represented by - + *
185 # strip function type out of each pin name
187 for i
in range(len(pingroup
)):
192 if fntype
not in '+-*':
195 fntype
= {'-': 'in', '+': 'out', '*': 'inout'}[fntype
]
196 self
.fntype
[pname
] = fntype
200 self
.pingroup
= pingroup
201 self
.gangedgroup
= gangedgrp
202 self
.bankspec
= bankspec
204 self
.origsuffix
= origsuffix
or suffix
208 # create consistent name suffixes
209 pingroup
= namesuffix(fname
, suffix
, pingroup
)
215 for name
in pingroup
[:limit
]:
217 name_
= "%s_%s" % (name
, suffix
)
220 if spec
and name
in spec
:
222 pin
= {mux
: (name_
, bank
)}
223 offs_bank
, offs_
= offs
226 idx_
+= bankspec
[bank
]
229 for name
in pingroup
:
231 name_
= "%s_%s" % (name
, suffix
)
238 idx_
, mux_
= spec
[name
]
240 pin
= {mux_
: (name_
, bank
)}
242 res
[idx_
].update(pin
)