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