include extra pin image and package marking
[pinmux.git] / src / spec / ifaceprint.py
1 #!/usr/bin/env python
2
3 from copy import deepcopy
4 from collections import OrderedDict
5 from math import pi
6 import os
7 import base64
8
9 cwd = os.path.split(os.path.abspath(__file__))[0]
10 lead_drawing = cwd + "/greatek_qfp_128L.png"
11 pack_drawing = cwd + "/greatek_qfp_128_fp.png"
12
13 def bond_int_to_ext(pin, bank):
14 """ note that internal numbering is 0-31 whereas the DISPLAY internal
15 numbering is 1-32. this uses the INTERNAL numbering.
16
17 side: N S E W
18
19 outer ring numbers: the python list order of the outer pads
20 middle numbers: the package number wires (plus side they are on)
21 inner numbers: the IO pad *python internal (0-31)* numbers plus side
22
23 0 1 2 3 N 34 35 36 37
24 N102 N101 N100 99 N 68 N67 N66 N65
25 W29 W30 W31 N0 N N31 E29 E30 E31
26
27 25 103 W28 E28 64 25
28 W W W E E E
29 0 128 W3 E3 39 0
30
31 W2 W1 W0 S0 S S31 E0 E1 E2
32 S1 S2 S3 4 S 35 S36 S37 S38
33 0 1 2 3 S 34 35 36 37
34
35 """
36 # returns side, order-on-the-side, pin number
37 if bank == 'N':
38 return 'N', pin+3, 99-pin
39 if bank == 'S':
40 return 'S', pin+3, 4+pin
41 if bank == 'W':
42 if pin >= 29: # 29, 30, 31
43 return 'N', pin-29, 100+(31-pin)
44 if pin <= 2: # 0, 1, 2
45 return 'S', 2-pin, 3-pin
46 return 'W', 28-pin, 103+(28-pin)
47 if bank == 'E':
48 if pin >= 29:
49 return 'N', 35+(31-pin), 67-(31-pin)
50 if pin <= 2:
51 return 'S', pin+35, 36+pin
52 return 'E', 28-pin, 39+(pin-3)
53
54
55 def create_sv(fname, pins):
56 """unsophisticated drawer of an SVG
57 """
58
59 try:
60 import svgwrite
61 except ImportError:
62 print ("WARNING, no SVG image, not producing image %s" % fname)
63 return
64
65 # create internal to external map
66 bondmap = {'N': {}, 'S': {}, 'E': {}, 'W': {} }
67 padside = {'pads.north': 'N', 'pads.east': 'E', 'pads.south': 'S',
68 'pads.west': 'W'}
69 sidepad = {}
70 for pinpad, bank in padside.items():
71 sidepad[bank] = pinpad
72 for ipin in range(len(pins[pinpad])):
73 eside, enum, epinnum = bond_int_to_ext(ipin, bank)
74 bondmap[eside][enum] = (epinnum, ipin, bank)
75 with open("/tmp/bondmap.txt", "w") as f:
76 for k,v in bondmap.items():
77 f.write("%s\n" % k)
78 for enum, (epinnum, ipin, bank) in v.items():
79 f.write(" %d %d -> %s %d\n" % (enum, epinnum, bank, ipin))
80
81 scale = 15
82 outerscale = scale * 2.0
83
84 width = len(pins['pads.north']) * scale
85 height = len(pins['pads.east']) * scale
86 woffs = scale*40#-width/2
87 hoffs = scale*40#-height/2
88
89 nepads = bondmap['N'].keys()
90 nepads.sort()
91 wepads = bondmap['W'].keys()
92 wepads.sort()
93 eepads = bondmap['E'].keys()
94 eepads.sort()
95 sepads = bondmap['S'].keys()
96 sepads.sort()
97
98 owoffs = woffs + (width/2) - len(nepads)/2 * outerscale
99 ohoffs = hoffs + (height/2) - len(wepads)/2 * outerscale
100
101 dwg = svgwrite.Drawing(fname, profile='full',
102 size=(width+scale*85, height+scale*80))
103
104 # outer QFP rect
105 dwg.add(dwg.rect((owoffs-scale*2.5, ohoffs-scale*4.5),
106 (len(nepads)*outerscale+scale*9,
107 len(wepads)*outerscale+scale*13),
108 fill='white',
109 stroke=svgwrite.rgb(0, 128, 0, '%'),
110 stroke_width=scale/5.0))
111
112 # inner lead rect
113 dwg.add(dwg.rect((woffs-scale*2, hoffs-scale*2),
114 (width+scale*6, height+scale*6),
115 stroke=svgwrite.rgb(16, 255, 16, '%'),
116 stroke_width=scale/10.0))
117
118 # record the inner line (iopad) position so that the outer one can
119 # match with it
120 innerpos = {'N': {}, 'S': {}, 'E': {}, 'W': {} }
121
122 # create the inner diagram
123 for i, pin in enumerate(pins['pads.west']):
124 ht = hoffs + height - (i * scale) + scale*0.5
125 endline = (woffs-scale*4.5, ht-scale*0.5)
126 innerpos['W'][i] = endline
127 dwg.add(dwg.line((woffs-scale*2, ht-scale*0.5),
128 endline,
129 stroke=svgwrite.rgb(16, 255, 16, '%'),
130 stroke_width=scale/10.0))
131 dwg.add(dwg.text(pin.upper(), insert=(woffs-scale*14, ht),
132 fill='black'))
133 dwg.add(dwg.text("W%d" % (i+1), insert=(woffs-scale*1.5, ht),
134 fill='white'))
135
136 for i, pin in enumerate(pins['pads.east']):
137 ht = hoffs + height - (i * scale) + scale*0.5
138 wd = width + woffs + scale*2
139 endline = (wd+scale*4.5, ht-scale*0.5)
140 innerpos['E'][i] = endline
141 dwg.add(dwg.line((wd+scale*2, ht-scale*0.5),
142 endline,
143 stroke=svgwrite.rgb(16, 255, 16, '%'),
144 stroke_width=scale/10.0))
145 dwg.add(dwg.text(pin.upper(), insert=(wd+scale*5, ht-scale*0.25),
146 fill='black'))
147 dwg.add(dwg.text("E%d" % (i+1), insert=(wd, ht-scale*0.25),
148 fill='white'))
149
150 for i, pin in enumerate(pins['pads.north']):
151 wd = woffs + i * scale + scale*1.5
152 endline = (wd, hoffs-scale*4.5)
153 innerpos['N'][i] = endline
154 dwg.add(dwg.line((wd, hoffs-scale*2),
155 endline,
156 stroke=svgwrite.rgb(16, 255, 16, '%'),
157 stroke_width=scale/10.0))
158 pos=(wd, hoffs-scale*5.0)
159 txt = dwg.text(pin.upper(), insert=pos, fill='black')
160 txt.rotate(-90, pos)
161 dwg.add(txt)
162 pos=(wd+scale*0.25, hoffs-scale*0.25)
163 txt = dwg.text("N%d" % (i+1), insert=pos, fill='white')
164 txt.rotate(-90, pos)
165 dwg.add(txt)
166
167 for i, pin in enumerate(pins['pads.south']):
168 wd = woffs + i * scale + scale*1.5
169 ht = hoffs + height + scale*2
170 endline = (wd, ht+scale*4.5)
171 innerpos['S'][i] = endline
172 dwg.add(dwg.line((wd, ht+scale*2),
173 endline,
174 stroke=svgwrite.rgb(16, 255, 16, '%'),
175 stroke_width=scale/10.0))
176 pos=(wd-scale*0.25, ht+scale*5.0)
177 txt = dwg.text(pin.upper(), insert=pos, fill='black')
178 txt.rotate(90, pos)
179 dwg.add(txt)
180 pos=(wd-scale*0.25, ht+scale*0.25)
181 txt = dwg.text("S%d" % (i+1), insert=pos, fill='white')
182 txt.rotate(90, pos)
183 dwg.add(txt)
184
185 # north outer pads
186 for i in nepads:
187 (epinnum, ipin, bank) = pad = bondmap['N'][i]
188 wd = owoffs + i * outerscale + outerscale*1.5
189 endline = (wd, ohoffs-outerscale*2)
190 startline = innerpos[bank][ipin]
191 dwg.add(dwg.line(startline,
192 endline,
193 stroke=svgwrite.rgb(255, 16, 16, '%'),
194 stroke_width=scale/10.0))
195 pin = pins[sidepad[bank]][ipin]
196 pos=(wd, ohoffs-outerscale*4.0)
197 txt = dwg.text("%s (%s%d)" % (pin.upper(), bank, ipin+1),
198 insert=pos, fill='black')
199 txt.rotate(-90, pos)
200 dwg.add(txt)
201 pos=(wd, ohoffs-outerscale*2.5)
202 txt = dwg.text("%d N" % epinnum, insert=pos, fill='blue')
203 txt.rotate(-90, pos)
204 dwg.add(txt)
205
206 # west outer pads
207 for i in wepads:
208 (epinnum, ipin, bank) = pad = bondmap['W'][i]
209 ht = ohoffs + (i * outerscale) + outerscale*1.5
210 endline = (owoffs+outerscale*0.5, ht)
211 startline = innerpos[bank][ipin]
212 dwg.add(dwg.line(startline,
213 endline,
214 stroke=svgwrite.rgb(255, 16, 16, '%'),
215 stroke_width=scale/10.0))
216 pin = pins[sidepad[bank]][ipin]
217 pos = (owoffs-outerscale*6.0, ht)
218 dwg.add(dwg.text("%s (%s%d)" % (pin.upper(), bank, ipin+1),
219 pos,
220 fill='black'))
221 pos = (owoffs-outerscale*1.0, ht)
222 dwg.add(dwg.text("%d W" % epinnum, insert=pos,
223 fill='blue'))
224
225 # south outer pads
226 for i in sepads:
227 (epinnum, ipin, bank) = pad = bondmap['S'][i]
228 wd = owoffs + i * outerscale + outerscale*1.5
229 ht = ohoffs + len(wepads)*outerscale + outerscale*4
230 endline = (wd, ht)
231 startline = innerpos[bank][ipin]
232 dwg.add(dwg.line(startline,
233 endline,
234 stroke=svgwrite.rgb(255, 16, 16, '%'),
235 stroke_width=scale/10.0))
236 pin = pins[sidepad[bank]][ipin]
237 pos=(wd-outerscale*0.25, ht+outerscale*1.5)
238 txt = dwg.text("%s (%s%d)" % (pin.upper(), bank, ipin+1),
239 insert=pos, fill='black')
240 txt.rotate(90, pos)
241 dwg.add(txt)
242 pos=(wd-outerscale*0.25, ht+outerscale*0.5)
243 txt = dwg.text("%d S" % epinnum, insert=pos, fill='blue')
244 txt.rotate(90, pos)
245 dwg.add(txt)
246
247 # east outer pads
248 for i in eepads:
249 (epinnum, ipin, bank) = pad = bondmap['E'][i]
250 ht = ohoffs + (i * outerscale) + outerscale*1.5
251 wd = owoffs+len(nepads)*outerscale + outerscale*1
252 endline = (wd+outerscale*0.5, ht)
253 startline = innerpos[bank][ipin]
254 dwg.add(dwg.line(startline,
255 endline,
256 stroke=svgwrite.rgb(255, 16, 16, '%'),
257 stroke_width=scale/10.0))
258 pin = pins[sidepad[bank]][ipin]
259 pos = (wd+outerscale*2.5, ht)
260 dwg.add(dwg.text("%s (%s%d)" % (pin.upper(), bank, ipin+1),
261 pos,
262 fill='black'))
263 pos = (wd+outerscale*1.0, ht)
264 dwg.add(dwg.text("%d E" % epinnum, insert=pos,
265 fill='blue'))
266
267 # add QFP pack image in top-right
268 image_data = open(pack_drawing, "rb").read()
269 encoded = base64.b64encode(image_data).decode()
270 data = 'data:image/png;base64,{}'.format(encoded)
271 pos=(0, 0)
272 leads = svgwrite.image.Image(data, pos,
273 size=(327,300))
274 dwg.add(leads)
275 dwg.add(dwg.text("GREATEK QFP128L",
276 insert=(50,150),
277 font_size=20,
278 fill='black'))
279 dwg.add(dwg.text("D/W J1-03128-001",
280 insert=(50,180),
281 font_size=20,
282 fill='black'))
283
284
285 # add QFP lead image in centre
286 image_data = open(lead_drawing, "rb").read()
287 encoded = base64.b64encode(image_data).decode()
288 data = 'data:image/png;base64,{}'.format(encoded)
289 pos=(woffs+scale*3.5, hoffs+scale*3.5)
290 leads = svgwrite.image.Image(data, pos,
291 size=(400,400))
292 leads.rotate(-90, (pos[0]+200, pos[1]+200))
293 dwg.add(leads)
294
295 dwg.add(dwg.text("GREATEK ELECTRONICS INC.",
296 insert=(woffs+width/2-scale*5, woffs+height/2-scale*6),
297 fill='black'))
298 dwg.add(dwg.text("INNER LEAD DRAWING",
299 insert=(woffs+width/2-scale*5, woffs+height/2-scale*5),
300 fill='black'))
301 dwg.add(dwg.text("QFP 128L OPEN STAMPING",
302 insert=(woffs+width/2-scale*5, woffs+height/2-scale*4),
303 fill='black'))
304 dwg.add(dwg.text("BODY 14x20x2.75mm",
305 insert=(woffs+width/2-scale*5, woffs+height/2-scale*3),
306 fill='black'))
307 dwg.add(dwg.text("L/F PAD SIZE 236x236mil^2",
308 insert=(woffs+width/2-scale*5, woffs+height/2-scale*2),
309 fill='black'))
310
311 # add attribution
312 dwg.add(dwg.text("Libre-SOC ls180 QFP-128",
313 insert=(woffs+width/2-scale*5, woffs+height/2),
314 fill='black'))
315 dwg.add(dwg.text("In collaboration with LIP6.fr",
316 insert=(woffs+width/2-scale*5, woffs+height/2+scale),
317 fill='black'))
318 dwg.add(dwg.text("Cell Libraries by Chips4Makers",
319 insert=(woffs+width/2-scale*5, woffs+height/2+scale*2),
320 fill='black'))
321 dwg.add(dwg.text("IMEC TSMC 180nm",
322 insert=(woffs+width/2-scale*5, woffs+height/2+scale*3),
323 fill='black'))
324
325 # add package marking circles
326 pos = (owoffs-outerscale*0, ohoffs+len(wepads)*outerscale+outerscale*2.5)
327 dwg.add(dwg.circle(pos, scale*2,
328 fill='white',
329 stroke=svgwrite.rgb(16, 16, 16, '%'),
330 stroke_width=scale/5.0))
331 dwg.add(dwg.circle(pos, scale*1,
332 fill='black',
333 stroke=svgwrite.rgb(255, 16, 16, '%'),
334 stroke_width=scale/5.0))
335 pos = (owoffs+len(nepads)*outerscale+outerscale*2, ohoffs-outerscale*0.5)
336 dwg.add(dwg.circle(pos, scale*2,
337 fill='white',
338 stroke=svgwrite.rgb(16, 16, 16, '%'),
339 stroke_width=scale/5.0))
340
341
342 dwg.save()
343
344
345 def display(of, pins, banksel=None, muxwidth=4):
346 of.write("""\
347 | Pin | Mux0 | Mux1 | Mux2 | Mux3 |
348 | --- | ----------- | ----------- | ----------- | ----------- |
349 """)
350 pinidx = sorted(pins.keys())
351 for pin in pinidx:
352 pdata = pins.get(pin)
353 if banksel:
354 skip = False
355 for mux in range(muxwidth):
356 if mux not in pdata:
357 continue
358 name, bank = pdata[mux]
359 if banksel != bank:
360 skip = True
361 if skip:
362 continue
363 res = '| %3d |' % pin
364 for mux in range(muxwidth):
365 if mux not in pdata:
366 res += " |"
367 continue
368 name, bank = pdata[mux]
369 res += " %s %-9s |" % (bank, name)
370 of.write("%s\n" % res)
371
372
373 def fnsplit(f):
374 a = ''
375 n = 0
376 if not f.startswith('FB_'):
377 f2 = f.split('_')
378 if len(f2) == 2:
379 if f2[1].isdigit():
380 return f2[0], int(f2[1])
381 return f2[0], f2[1]
382 #print f
383 while f and not f[0].isdigit():
384 a += f[0]
385 f = f[1:]
386 return a, int(f) if f else None
387
388
389 def fnsort(f1, f2):
390 a1, n1 = fnsplit(f1)
391 a2, n2 = fnsplit(f2)
392 x = cmp(a1, a2)
393 if x != 0:
394 return x
395 return cmp(n1, n2)
396
397
398 def find_fn(fname, names):
399 for n in names:
400 if fname.startswith(n):
401 return n
402
403 def map_name(pinmap, fn, fblower, pin, rename):
404 if not rename:
405 if pin[:-1].isdigit():
406 print "map name digit", pin, fn, fblower
407 if fn in ['PWM', 'EINT', 'VDD', 'VSS']:
408 return fn.lower() + pin.lower()
409 if fn == 'GPIO':
410 return 'gpio' + pin[1:].lower()
411 return pin.lower()
412 pin = pin.lower()
413 if fn == 'GPIO':
414 pk = '%s%s_%s' % (fblower, pin[0], pin[:-1])
415 elif pin[:-1].isdigit() and fn != 'EINT':
416 pk = '%s%s_out' % (fblower, pin[:-1])
417 else:
418 pk = '%s_%s' % (fblower, pin[:-1])
419 print "map name", pk, fblower, pinmap.has_key(pk)
420 if not pinmap.has_key(pk):
421 return pin.lower()
422 remapped = pinmap[pk]
423 uscore = remapped.find('_')
424 if uscore == -1:
425 return pin.lower()
426 fn, pin = remapped[:uscore], remapped[uscore+1:] + pin[-1]
427 return pin.lower()
428
429 def python_pindict(of, pinmap, pins, function_names, dname, remap):
430
431 res = OrderedDict()
432 of.write("\n%s = OrderedDict()\n" % dname)
433
434 for k, pingroup in pins.byspec.items():
435 (a, n) = k.split(":")
436 if n.isdigit():
437 a = "%s%s" % (a, n)
438 fblower = a.lower()
439 of.write("%s['%s'] = [ " % (dname, fblower))
440 res[fblower] = []
441 count = 0
442 for i, p in enumerate(pingroup):
443 name = map_name(pinmap, k[0], fblower, p, remap)
444 res[fblower].append(name)
445 of.write("'%s', " % name)
446 count += 1
447 if count == 4 and i != len(pingroup)-1:
448 of.write("\n ")
449 count = 0
450 of.write("]\n")
451 print " dict %s" % dname, a, n, pingroup
452 of.write("\n\n")
453 return res
454
455 def python_dict_fns(of, pinmap, pins, function_names):
456 of.write("# auto-generated by Libre-SOC pinmux program: do not edit\n")
457 of.write("# python src/pinmux_generator.py -v -s {spec} -o {output}\n")
458 of.write("# use OrderedDict to fix stable order for JTAG Boundary Scan\n")
459 of.write("from collections import OrderedDict\n")
460
461 fn_names = function_names.keys()
462 fns = {}
463
464 fnidx = list(fns.keys())
465 fnidx.sort(key=fnsplit)
466
467 print "python fnames", function_names
468 print "python speckeys", pins.byspec.keys()
469 print "python dict fns", dir(pins.gpio)
470 print pins.gpio.pinfn('', '')
471 print pins.pwm.pinfn('', '')
472 print pins.sdmmc.pinfn('', '')
473 print "by spec", pins.byspec
474 print pinmap
475
476 pd = python_pindict(of, {}, pins, function_names, 'pindict', False)
477 ld = python_pindict(of, pinmap, pins, function_names, 'litexdict', True)
478
479 print "pd", pd
480 print "ld", ld
481 # process results and create name map
482 litexmap = OrderedDict()
483 for k in pd.keys():
484 pl = pd[k]
485 ll = ld[k]
486 for pname, lname in zip(pl, ll):
487 pname = "%s_%s" % (k, pname[:-1]) # strip direction +/-/*
488 lname = lname[:-1] # strip direction +/-/*
489 if k in ['eint', 'pwm', 'gpio', 'vdd', 'vss']: # sigh
490 lname = "%s_%s" % (k, lname)
491 litexmap[pname] = lname
492 print "litexmap", litexmap
493 of.write("litexmap = {\n")
494 for k, v in litexmap.items():
495 of.write("\t'%s': '%s',\n" % (k, v))
496 of.write("}\n")
497 return litexmap
498
499
500 def display_fns(of, bankspec, pins, function_names):
501 fn_names = function_names.keys()
502 fns = {}
503 for (pin, pdata) in pins.items():
504 for mux in range(0, 4): # skip GPIO for now
505 if mux not in pdata:
506 continue
507 name, bank = pdata[mux]
508 assert name is not None, str(bank)
509 if name not in fns:
510 fns[name] = []
511 fns[name].append((pin - bankspec[bank], mux, bank))
512
513 fnidx = list(fns.keys())
514 fnidx.sort(key=fnsplit)
515 current_fn = None
516 for fname in fnidx:
517 fnbase = find_fn(fname, fn_names)
518 #fblower = fnbase.lower()
519 assert fnbase in function_names, "fn %s not in descriptions %s" % \
520 (fname, str(function_names.keys()))
521 #print "name", fname, fnbase
522 if fnbase != current_fn:
523 if current_fn is not None:
524 of.write('\n')
525 of.write("## %s\n\n%s\n\n" % (fnbase, function_names[fnbase]))
526 current_fn = fnbase
527 of.write("* %-9s :" % fname)
528 for (pin, mux, bank) in fns[fname]:
529 of.write(" %s%d/%d" % (bank, pin, mux))
530 of.write('\n')
531
532 return fns
533
534
535 def check_functions(of, title, bankspec, fns, pins, required, eint, pwm,
536 descriptions=None):
537 fns = deepcopy(fns)
538 pins = deepcopy(pins)
539 if descriptions is None:
540 descriptions = {}
541 fnidx = fns.keys()
542
543 #print dir(fns)
544 #print dir(pins)
545
546 of.write("# Pinmap for %s\n\n" % title)
547
548 print "fn_idx", fnidx
549 print "fns", fns
550 print "fnspec", pins.fnspec.keys()
551 print "required", required
552 for name in required:
553 of.write("## %s\n\n" % name)
554 if descriptions and name in descriptions:
555 of.write("%s\n\n" % descriptions[name])
556
557 name = name.split(':')
558 if len(name) == 2:
559 findbank = name[0][0]
560 findmux = int(name[0][1:])
561 name = name[1]
562 else:
563 name = name[0]
564 findbank = None
565 findmux = None
566 name = name.split('/')
567 if len(name) == 2:
568 count = int(name[1])
569 else:
570 count = 100000
571 name = name[0]
572 #print name
573 found = set()
574 pinfound = {}
575 located = set()
576 for fname in fnidx:
577 if not fname.startswith(name):
578 continue
579 for k in pins.fnspec.keys():
580 if fname.startswith(k):
581 fk = list(pins.fnspec[k].keys())
582 fn = pins.fnspec[k]
583 fn = fn[fk[0]]
584 #print fname, fn, dir(fn)
585 if count == 100000:
586 count = len(fn.pingroup)
587 for pin, mux, bank in fns[fname]:
588 if findbank is not None:
589 if findbank != bank:
590 continue
591 if findmux != mux:
592 continue
593 pin_ = pin + bankspec[bank]
594 if pin_ in pins:
595 pinfound[pin_] = (fname, pin_, bank, pin, mux)
596
597 pinidx = sorted(pinfound.keys())
598
599 fname = None
600 removedcount = 0
601 print ("pinidx", pinidx)
602 for pin_ in pinidx:
603 fname, pin_, bank, pin, mux = pinfound[pin_]
604 if fname in found:
605 continue
606 found.add(fname)
607 if len(found) > count:
608 continue
609 del pins[pin_]
610 removedcount += 1
611 of.write("* %s %d %s%d/%d\n" % (fname, pin_, bank, pin, mux))
612
613 print fns
614 if removedcount != count:
615 if fname is None:
616 print "no match between required and available pins"
617 else:
618 print ("not all found", name, removedcount, count, title, found,
619 fns[fname])
620 print ("pins found", pinfound)
621
622 # fnidx.sort(fnsort)
623 of.write('\n')
624
625 # gpios
626 gpios = []
627 for name in descriptions.keys():
628 if not name.startswith('GPIO'):
629 continue
630 if name == 'GPIO':
631 continue
632 gpios.append(name)
633 gpios.sort()
634
635 if gpios:
636 of.write("## GPIO\n\n")
637
638 for fname in gpios:
639 if fname in found:
640 continue
641 desc = ''
642 if descriptions and fname in descriptions:
643 desc = ': %s' % descriptions[fname]
644 bank = fname[4]
645 pin = int(fname[7:])
646 pin_ = pin + bankspec[bank]
647 if pin_ not in pins:
648 continue
649 del pins[pin_]
650 found.add(fname)
651 of.write("* %-8s %d %s%-2d %s\n" % (fname, pin_, bank, pin, desc))
652 of.write('\n')
653
654 if eint:
655 display_group(of, bankspec, "EINT", eint, fns, pins, descriptions)
656 if pwm:
657 display_group(of, bankspec, "PWM", pwm, fns, pins, descriptions)
658
659 of.write("## Unused Pinouts (spare as GPIO) for '%s'\n\n" % title)
660 if descriptions and 'GPIO' in descriptions:
661 of.write("%s\n\n" % descriptions['GPIO'])
662 display(of, pins)
663 of.write('\n')
664
665 return pins # unused
666
667
668 def display_group(of, bankspec, title, todisplay, fns, pins, descriptions):
669 of.write("## %s\n\n" % title)
670
671 found = set()
672 for fname in todisplay:
673 desc = ''
674 if descriptions and fname in descriptions:
675 desc = ': %s' % descriptions[fname]
676 fname = fname.split(':')
677 if len(fname) == 2:
678 findbank = fname[0][0]
679 findmux = int(fname[0][1:])
680 fname = fname[1]
681 else:
682 fname = fname[0]
683 findbank = None
684 findmux = None
685 for (pin, mux, bank) in fns[fname]:
686 if findbank is not None:
687 if findbank != bank:
688 continue
689 if findmux != mux:
690 continue
691 if fname in found:
692 continue
693 pin_ = pin + bankspec[bank]
694 if pin_ not in pins:
695 continue
696 del pins[pin_]
697 found.add(fname)
698 of.write("* %s %d %s%d/%d %s\n" %
699 (fname, pin_, bank, pin, mux, desc))
700 of.write('\n')
701
702
703 def display_fixed(of, fixed, offs):
704
705 fkeys = sorted(fixed.keys())
706 pin_ = offs
707 res = []
708 for pin, k in enumerate(fkeys):
709 of.write("## %s\n\n" % k)
710 prevname = ''
711 linecount = 0
712 for name in fixed[k]:
713 if linecount == 4:
714 linecount = 0
715 of.write('\n')
716 if prevname[:2] == name[:2] and linecount != 0:
717 of.write(" %s" % name)
718 linecount += 1
719 else:
720 if linecount != 0:
721 of.write('\n')
722 of.write("* %d: %d %s" % (pin_, pin, name))
723 linecount = 1
724 res.append((pin_, name))
725
726 prevname = name
727 pin_ += 1
728 if linecount != 0:
729 of.write('\n')
730 of.write('\n')
731
732 return res