add some documentation to the spec modules
[pinmux.git] / src / spec / interfaces.py
1 #!/usr/bin/env python
2
3 from spec.pinfunctions import pinspec
4 from copy import deepcopy
5
6 def namesuffix(name, suffix, namelist):
7 names = []
8 for n in namelist:
9 if n:
10 names.append("%s%s_%s" % (name, suffix, n))
11 else:
12 names.append("%s_%s" % (name, suffix))
13 return names
14
15
16 class PinGen(object):
17 """ a meta-helper which creates pins from the pinspec
18 and adds them to the pinouts.
19
20 __call__ is used to effectively create a lambda function, which
21 in combination with setattr (below) gives the function a name
22 in the Pinouts class, according to the pinspec.
23 """
24 def __init__(self, pinouts, fname, pinfn, bankspec):
25 self.pinouts = pinouts
26 self.bankspec = bankspec
27 self.pinfn = pinfn
28 self.fname = fname
29
30 def __call__(self, suffix, offs, bank, mux,
31 start=None, limit=None, spec=None, origsuffix=None):
32 pingroup = self.pinfn(suffix, bank)
33 if isinstance(pingroup, tuple):
34 prefix, pingroup = pingroup
35 else:
36 prefix = self.fname
37 if start and limit: # limit turns into an offset from start
38 limit = start + limit
39 pingroup = pingroup[start:limit] # see comment in spec.pinfunctions
40 pins = Pins(prefix, pingroup, self.bankspec,
41 suffix, offs, bank, mux,
42 spec, origsuffix=suffix)
43 self.pinouts.pinmerge(pins)
44
45 # pinouts class
46
47 class Pinouts(object):
48 def __init__(self, bankspec):
49 self.bankspec = bankspec
50 self.pins = {}
51 self.fnspec = {}
52 for fname, pinfn in pinspec:
53 if isinstance(pinfn, tuple):
54 name, pinfn = pinfn
55 else:
56 name = pinfn.__name__
57 setattr(self, name, PinGen(self, fname, pinfn, self.bankspec))
58
59 def __contains__(self, k):
60 return k in self.pins
61
62 def has_key(self, k):
63 return k in self.pins
64
65 def add_spec(self, k, v):
66 self.fnspec[k] = v
67
68 def update(self, pinidx, v):
69 if pinidx not in self.pins:
70 self.pins[pinidx] = v
71 else:
72 for k in v:
73 assert k not in self.pins[pinidx], \
74 "pin %d position %d already taken\n%s\n%s" % \
75 (pinidx, k, str(v), self.pins[pinidx])
76 self.pins[pinidx].update(v)
77
78 def keys(self):
79 return self.pins.keys()
80
81 def items(self):
82 return self.pins.items()
83
84 def get(self, k):
85 return self.pins[k]
86
87 def __len__(self):
88 return len(self.pins)
89
90 def __delitem__(self, k):
91 del self.pins[k]
92
93 def __getitem__(self, k):
94 return self.pins[k]
95
96 def pinmerge(self, fn):
97 # hack, store the function specs in the pins dict
98 fname = fn.fname
99 suffix = fn.origsuffix
100 bank = fn.bank
101
102 if not hasattr(self, 'fnspec'):
103 self.fnspec = pins
104 if fname == 'GPIO':
105 fname = fname + bank
106 assert 'EINT' not in self
107 if fname not in self.fnspec:
108 self.add_spec(fname, {})
109 if suffix or fname == 'EINT' or fname == 'PWM':
110 specname = fname + suffix
111 else:
112 specname = fname
113 #print "fname bank specname suffix ", fname, bank, specname, repr(
114 # suffix)
115 if specname in self.fnspec[fname]:
116 # ok so some declarations may bring in different
117 # names at different stages (EINT, PWM, flexbus1/2)
118 # so we have to merge the names in. main thing is
119 # the pingroup
120 tomerge = self.fnspec[fname][specname]
121 for p in fn.pingroup:
122 if p not in tomerge.pingroup:
123 tomerge.pingroup.append(p)
124 tomerge.pins.update(fn.pins)
125 tomerge.fntype.update(fn.fntype)
126 else:
127 self.fnspec[fname][specname] = deepcopy(fn)
128
129 # merge actual pins
130 for (pinidx, v) in fn.pins.items():
131 self.update(pinidx, v)
132
133
134 class Pins(object):
135
136 def __init__(self, fname, pingroup, bankspec, suffix, offs, bank, mux,
137 spec=None, limit=None, origsuffix=None):
138
139 # function type can be in, out or inout, represented by - + *
140 # strip function type out of each pin name
141 self.fntype = {}
142 for i in range(len(pingroup)):
143 pname = pingroup[i]
144 if not pname:
145 continue
146 fntype = pname[-1]
147 if fntype not in '+-*':
148 continue
149 pname = pname[:-1]
150 fntype = {'-': 'in', '+': 'out', '*': 'inout'}[fntype]
151 self.fntype[pname] = fntype
152 pingroup[i] = pname
153
154 self.fname = fname
155 self.pingroup = pingroup
156 self.bankspec = bankspec
157 self.suffix = suffix
158 self.origsuffix = origsuffix or suffix
159 self.bank = bank
160 self.mux = mux
161
162 # create consistent name suffixes
163 pingroup = namesuffix(fname, suffix, pingroup)
164 suffix = '' # hack
165
166 res = {}
167 names = {}
168 idx = 0
169 for name in pingroup[:limit]:
170 if suffix and name:
171 name_ = "%s_%s" % (name, suffix)
172 else:
173 name_ = name
174 if spec and name in spec:
175 continue
176 pin = {mux: (name_, bank)}
177 offs_bank, offs_ = offs
178 idx_ = offs_ + idx
179 idx += 1
180 idx_ += bankspec[bank]
181 res[idx_] = pin
182 names[name] = idx_
183 for name in pingroup:
184 if suffix and name:
185 name_ = "%s_%s" % (name, suffix)
186 else:
187 name_ = name
188 if not spec:
189 continue
190 if name not in spec:
191 continue
192 idx_, mux_, bank_ = spec[name]
193 idx_ = names[idx_]
194 pin = {mux_: (name_, bank_)}
195 if idx_ in res:
196 res[idx_].update(pin)
197 else:
198 res[idx_] = pin
199
200 self.pins = res