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