add i_class preliminary draft
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 6 Mar 2018 06:54:44 +0000 (06:54 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 6 Mar 2018 06:54:44 +0000 (06:54 +0000)
shakti/i_class/pinouts.mdwn [new file with mode: 0644]
shakti/i_class/pinouts.py [new file with mode: 0644]

diff --git a/shakti/i_class/pinouts.mdwn b/shakti/i_class/pinouts.mdwn
new file mode 100644 (file)
index 0000000..56c42a7
--- /dev/null
@@ -0,0 +1,512 @@
+# Pinouts (PinMux)
+
+auto-generated by [[pinouts.py]]
+
+[[!toc  ]]
+
+| Pin | Mux0        | Mux1        | Mux2        | Mux3        |
+| --- | ----------- | ----------- | ----------- | ----------- |
+|   0 | A GPIOA0    | A SPI0_CLK  | A PWM_0     |             |
+|   1 | A GPIOA1    | A SPI0_NSS  | A PWM_1     |             |
+|   2 | A GPIOA2    | A SPI0_MOSI | A PWM_2     |             |
+|   3 | A GPIOA3    | A SPI0_MISO | A PWM_3     |             |
+|   4 | A GPIOA4    | A SPI1_CLK  | A PWM_4     |             |
+|   5 | A GPIOA5    | A SPI1_NSS  | A PWM_5     |             |
+|   6 | A GPIOA6    | A SPI1_MOSI | A PWM_6     |             |
+|   7 | A GPIOA7    | A SPI1_MISO | A PWM_7     |             |
+|   8 | A GPIOA8    | A UART0_TX  | A PWM_8     |             |
+|   9 | A GPIOA9    | A UART0_RX  | A PWM_9     |             |
+|  10 | A GPIOA10   | A UART1_TX  | A PWM_10    |             |
+|  11 | A GPIOA11   | A UART1_RX  | A PWM_11    |             |
+|  12 | A GPIOA12   | A TWI0_SDA  | A PWM_12    |             |
+|  13 | A GPIOA13   | A TWI0_SCL  | A PWM_13    |             |
+|  14 | A GPIOA14   | A TWI1_SDA  | A PWM_14    |             |
+|  15 | A GPIOA15   | A TWI1_SCL  | A PWM_15    |             |
+|  16 | B GPIOB0    | B SPI2_CLK  | B PWM_16    |             |
+|  17 | B GPIOB1    | B SPI2_NSS  | B PWM_17    |             |
+|  18 | B GPIOB2    | B SPI2_MOSI | B PWM_18    |             |
+|  19 | B GPIOB3    | B SPI2_MISO | B PWM_19    |             |
+|  20 | B GPIOB4    | B UART2_TX  | B PWM_20    |             |
+|  21 | B GPIOB5    | B UART2_RX  | B PWM_21    |             |
+|  22 | B GPIOB6    | B UART3_TX  | B PWM_22    |             |
+|  23 | B GPIOB7    | B UART3_RX  | B PWM_23    |             |
+|  24 | B GPIOB8    | B UART4_TX  | B PWM_24    |             |
+|  25 | B GPIOB9    | B UART4_RX  | B PWM_25    |             |
+|  26 | B GPIOB10   | B TWI2_SDA  | B PWM_26    |             |
+|  27 | B GPIOB11   | B TWI2_SCL  | B PWM_27    |             |
+|  28 | B GPIOB12   | B TWI3_SDA  | B PWM_28    |             |
+|  29 | B GPIOB13   | B TWI3_SCL  | B PWM_29    |             |
+|  30 | B GPIOB14   | B UART5_TX  | B PWM_30    |             |
+|  31 | B GPIOB15   | B UART5_RX  | B PWM_31    |             |
+|  32 |             | C ULPI0_CK  |             |             |
+|  33 |             | C ULPI0_DIR |             |             |
+|  34 |             | C ULPI0_STP |             |             |
+|  35 |             | C ULPI0_NXT |             |             |
+|  36 |             | C ULPI0_D0  |             |             |
+|  37 |             | C ULPI0_D1  |             |             |
+|  38 |             | C ULPI0_D2  |             |             |
+|  39 |             | C ULPI0_D3  |             |             |
+|  40 |             | C ULPI0_D4  |             |             |
+|  41 |             | C ULPI0_D5  |             |             |
+|  42 |             | C ULPI0_D6  |             |             |
+|  43 |             | C ULPI0_D7  |             |             |
+|  44 |             | C SPI0_CLK  |             |             |
+|  45 |             | C SPI0_NSS  |             |             |
+|  46 |             | C SPI0_MOSI |             |             |
+|  47 |             | C SPI0_MISO |             |             |
+|  48 |             | D SD0_CMD   |             |             |
+|  49 |             | D SD0_CLK   |             |             |
+|  50 |             | D SD0_D0    |             |             |
+|  51 |             | D SD0_D1    |             |             |
+|  52 |             | D SD0_D2    |             |             |
+|  53 |             | D SD0_D3    |             |             |
+|  54 |             | D JTAG0_MS  |             |             |
+|  55 |             | D JTAG0_DI  |             |             |
+|  56 |             | D JTAG0_DO  |             |             |
+|  57 |             | D JTAG0_CK  |             |             |
+|  58 |             | D UART0_TX  |             |             |
+|  59 |             | D UART0_RX  |             |             |
+|  60 |             | D TWI0_SDA  |             |             |
+|  61 |             | D TWI0_SCL  |             |             |
+|  62 |             | D UART1_TX  |             |             |
+|  63 |             | D UART1_RX  |             |             |
+|  64 |             | E FB_AD0    |             |             |
+|  65 |             | E FB_AD1    |             |             |
+|  66 |             | E FB_AD2    |             |             |
+|  67 |             | E FB_AD3    |             |             |
+|  68 |             | E FB_AD4    |             |             |
+|  69 |             | E FB_AD5    |             |             |
+|  70 |             | E FB_AD6    |             |             |
+|  71 |             | E FB_AD7    |             |             |
+|  72 |             | E FB_CS0    |             |             |
+|  73 |             | E FB_CS1    |             |             |
+|  74 |             | E FB_ALE    |             |             |
+|  75 |             | E FB_OE     |             |             |
+|  76 |             | E FB_RW     |             |             |
+|  77 |             | E FB_TA     |             |             |
+|  78 |             | E FB_CLK    |             |             |
+|  79 |             | E FB_A0     |             |             |
+|  80 |             | E FB_A1     |             |             |
+|  81 |             | E FB_TS     |             |             |
+|  82 |             | E FB_TBST   |             |             |
+|  83 |             | E FB_TSIZ0  |             |             |
+|  84 |             | E FB_TSIZ1  |             |             |
+|  85 |             | E FB_BWE0   |             |             |
+|  86 |             | E FB_BWE1   |             |             |
+|  87 |             | E FB_BWE2   |             |             |
+|  88 |             | E FB_BWE3   |             |             |
+|  89 |             | E FB_CS2    |             |             |
+|  90 |             | E FB_CS3    |             |             |
+|  91 |             | E FB_CS4    |             |             |
+|  92 |             | E FB_CS5    |             |             |
+|  94 |             | E FB_AD8    |             |             |
+|  95 |             | E FB_AD9    |             |             |
+|  96 |             | E FB_AD10   |             |             |
+|  97 |             | E FB_AD11   |             |             |
+|  98 |             | E FB_AD12   |             |             |
+|  99 |             | E FB_AD13   |             |             |
+| 100 |             | E FB_AD14   |             |             |
+| 101 |             | E FB_AD15   |             |             |
+
+# Pinouts (Fixed function)
+
+## CTRL_SYS
+
+* 101: 0 TEST
+* 102: 0 BOOT_SEL
+* 103: 0 NMI#
+* 104: 0 RESET#
+* 105: 0 CLK24M_IN CLK24M_OUT CLK32K_IN CLK32K_OUT
+* 109: 0 PLLTEST PLLREGIO PLLVP25 PLLDV
+* 113: 0 PLLVREG PLLGND
+
+## POWER_CPU
+
+* 115: 1 VDD0_CPU VDD1_CPU VDD2_CPU VDD3_CPU
+* 119: 1 VDD4_CPU VDD5_CPU
+* 121: 1 GND0_CPU GND1_CPU GND2_CPU GND3_CPU
+* 125: 1 GND4_CPU GND5_CPU
+
+## POWER_DLL
+
+* 127: 2 VDD0_DLL VDD1_DLL VDD2_DLL
+* 130: 2 GND0_DLL GND1_DLL GND2_DLL
+
+## POWER_GPIO
+
+* 133: 3 VDD_GPIOA VDD_GPIOB VDD_GPIOC VDD_GPIOD
+* 137: 3 VDD_GPIOE
+* 138: 3 GND_GPIOA GND_GPIOB GND_GPIOC GND_GPIOD
+* 142: 3 GND_GPIOE
+
+## POWER_INT
+
+* 143: 4 VDD0_INT VDD1_INT VDD2_INT VDD3_INT
+* 147: 4 VDD4_INT VDD5_INT VDD6_INT VDD7_INT
+* 151: 4 VDD8_INT VDD9_INT
+* 153: 4 GND0_INT GND1_INT GND2_INT GND3_INT
+* 157: 4 GND4_INT GND5_INT GND6_INT GND7_INT
+* 161: 4 GND8_INT GND9_INT
+
+# Functions (PinMux)
+
+auto-generated by [[pinouts.py]]
+
+## FB
+
+MC68k FlexBus
+
+* FB_A0     : E15/1
+* FB_A1     : E16/1
+* FB_AD0    : E0/1
+* FB_AD1    : E1/1
+* FB_AD2    : E2/1
+* FB_AD3    : E3/1
+* FB_AD4    : E4/1
+* FB_AD5    : E5/1
+* FB_AD6    : E6/1
+* FB_AD7    : E7/1
+* FB_AD8    : E30/1
+* FB_AD9    : E31/1
+* FB_AD10   : E32/1
+* FB_AD11   : E33/1
+* FB_AD12   : E34/1
+* FB_AD13   : E35/1
+* FB_AD14   : E36/1
+* FB_AD15   : E37/1
+* FB_ALE    : E10/1
+* FB_BWE0   : E21/1
+* FB_BWE1   : E22/1
+* FB_BWE2   : E23/1
+* FB_BWE3   : E24/1
+* FB_CLK    : E14/1
+* FB_CS0    : E8/1
+* FB_CS1    : E9/1
+* FB_CS2    : E25/1
+* FB_CS3    : E26/1
+* FB_CS4    : E27/1
+* FB_CS5    : E28/1
+* FB_OE     : E11/1
+* FB_RW     : E12/1
+* FB_TA     : E13/1
+* FB_TBST   : E18/1
+* FB_TS     : E17/1
+* FB_TSIZ0  : E19/1
+* FB_TSIZ1  : E20/1
+
+## JTAG0
+
+JTAG
+
+* JTAG0_CK  : D9/1
+* JTAG0_DI  : D7/1
+* JTAG0_DO  : D8/1
+* JTAG0_MS  : D6/1
+
+## PWM
+
+PWM (pulse-width modulation)
+
+* PWM_0     : A0/2
+* PWM_1     : A1/2
+* PWM_2     : A2/2
+* PWM_3     : A3/2
+* PWM_4     : A4/2
+* PWM_5     : A5/2
+* PWM_6     : A6/2
+* PWM_7     : A7/2
+* PWM_8     : A8/2
+* PWM_9     : A9/2
+* PWM_10    : A10/2
+* PWM_11    : A11/2
+* PWM_12    : A12/2
+* PWM_13    : A13/2
+* PWM_14    : A14/2
+* PWM_15    : A15/2
+* PWM_16    : B0/2
+* PWM_17    : B1/2
+* PWM_18    : B2/2
+* PWM_19    : B3/2
+* PWM_20    : B4/2
+* PWM_21    : B5/2
+* PWM_22    : B6/2
+* PWM_23    : B7/2
+* PWM_24    : B8/2
+* PWM_25    : B9/2
+* PWM_26    : B10/2
+* PWM_27    : B11/2
+* PWM_28    : B12/2
+* PWM_29    : B13/2
+* PWM_30    : B14/2
+* PWM_31    : B15/2
+
+## SD0
+
+SD/MMC 0
+
+* SD0_CLK   : D1/1
+* SD0_CMD   : D0/1
+* SD0_D0    : D2/1
+* SD0_D1    : D3/1
+* SD0_D2    : D4/1
+* SD0_D3    : D5/1
+
+## SPI0
+
+SPI (Serial Peripheral Interface) 0
+
+* SPI0_CLK  : A0/1 C12/1
+* SPI0_MISO : A3/1 C15/1
+* SPI0_MOSI : A2/1 C14/1
+* SPI0_NSS  : A1/1 C13/1
+
+## SPI1
+
+SPI (Serial Peripheral Interface) 1
+
+* SPI1_CLK  : A4/1
+* SPI1_MISO : A7/1
+* SPI1_MOSI : A6/1
+* SPI1_NSS  : A5/1
+
+## SPI2
+
+SPI (Serial Peripheral Interface) 2
+
+* SPI2_CLK  : B0/1
+* SPI2_MISO : B3/1
+* SPI2_MOSI : B2/1
+* SPI2_NSS  : B1/1
+
+## TWI0
+
+I2C 0
+
+* TWI0_SCL  : A13/1 D13/1
+* TWI0_SDA  : A12/1 D12/1
+
+## TWI1
+
+I2C 1
+
+* TWI1_SCL  : A15/1
+* TWI1_SDA  : A14/1
+
+## TWI2
+
+I2C 2
+
+* TWI2_SCL  : B11/1
+* TWI2_SDA  : B10/1
+
+## TWI3
+
+I2C 3
+
+* TWI3_SCL  : B13/1
+* TWI3_SDA  : B12/1
+
+## UART0
+
+UART (TX/RX) 0
+
+* UART0_RX  : A9/1 D11/1
+* UART0_TX  : A8/1 D10/1
+
+## UART1
+
+UART (TX/RX) 1
+
+* UART1_RX  : A11/1 D15/1
+* UART1_TX  : A10/1 D14/1
+
+## UART2
+
+UART (TX/RX) 2
+
+* UART2_RX  : B5/1
+* UART2_TX  : B4/1
+
+## UART3
+
+UART (TX/RX) 3
+
+* UART3_RX  : B7/1
+* UART3_TX  : B6/1
+
+## UART4
+
+UART (TX/RX) 4
+
+* UART4_RX  : B9/1
+* UART4_TX  : B8/1
+
+## UART5
+
+UART (TX/RX) 5
+
+* UART5_RX  : B15/1
+* UART5_TX  : B14/1
+
+## ULPI0
+
+ULPI (USB Low Pin-count) 0
+
+* ULPI0_CK  : C0/1
+* ULPI0_D0  : C4/1
+* ULPI0_D1  : C5/1
+* ULPI0_D2  : C6/1
+* ULPI0_D3  : C7/1
+* ULPI0_D4  : C8/1
+* ULPI0_D5  : C9/1
+* ULPI0_D6  : C10/1
+* ULPI0_D7  : C11/1
+* ULPI0_DIR : C1/1
+* ULPI0_NXT : C3/1
+* ULPI0_STP : C2/1
+
+# Pinmap for Robotics
+
+## FB
+
+* FB_AD0 64 E0/1
+* FB_AD1 65 E1/1
+* FB_AD2 66 E2/1
+* FB_AD3 67 E3/1
+* FB_AD4 68 E4/1
+* FB_AD5 69 E5/1
+* FB_AD6 70 E6/1
+* FB_AD7 71 E7/1
+* FB_CS0 72 E8/1
+* FB_CS1 73 E9/1
+* FB_ALE 74 E10/1
+* FB_OE 75 E11/1
+* FB_RW 76 E12/1
+* FB_TA 77 E13/1
+* FB_CLK 78 E14/1
+* FB_A0 79 E15/1
+* FB_A1 80 E16/1
+* FB_TS 81 E17/1
+* FB_TBST 82 E18/1
+* FB_TSIZ0 83 E19/1
+* FB_TSIZ1 84 E20/1
+* FB_BWE0 85 E21/1
+* FB_BWE1 86 E22/1
+* FB_BWE2 87 E23/1
+* FB_BWE3 88 E24/1
+* FB_CS2 89 E25/1
+* FB_CS3 90 E26/1
+* FB_CS4 91 E27/1
+* FB_CS5 92 E28/1
+* FB_AD8 94 E30/1
+* FB_AD9 95 E31/1
+* FB_AD10 96 E32/1
+* FB_AD11 97 E33/1
+* FB_AD12 98 E34/1
+* FB_AD13 99 E35/1
+* FB_AD14 100 E36/1
+* FB_AD15 101 E37/1
+
+## ULPI0/8
+
+* ULPI0_CK 32 C0/1
+* ULPI0_DIR 33 C1/1
+* ULPI0_STP 34 C2/1
+* ULPI0_NXT 35 C3/1
+* ULPI0_D0 36 C4/1
+* ULPI0_D1 37 C5/1
+* ULPI0_D2 38 C6/1
+* ULPI0_D3 39 C7/1
+
+## SD0
+
+* SD0_CMD 48 D0/1
+* SD0_CLK 49 D1/1
+* SD0_D0 50 D2/1
+* SD0_D1 51 D3/1
+* SD0_D2 52 D4/1
+* SD0_D3 53 D5/1
+
+## JTAG0
+
+* JTAG0_MS 54 D6/1
+* JTAG0_DI 55 D7/1
+* JTAG0_DO 56 D8/1
+* JTAG0_CK 57 D9/1
+
+## UART0
+
+* UART0_TX 8 A8/1
+* UART0_RX 9 A9/1
+
+## SPI0
+
+* SPI0_CLK 0 A0/1
+* SPI0_NSS 1 A1/1
+* SPI0_MOSI 2 A2/1
+* SPI0_MISO 3 A3/1
+
+## TWI0
+
+* TWI0_SDA 12 A12/1
+* TWI0_SCL 13 A13/1
+
+## PWM
+
+* PWM_4 4 A4/2 
+* PWM_5 5 A5/2 
+* PWM_6 6 A6/2 
+* PWM_7 7 A7/2 
+* PWM_10 10 A10/2 
+* PWM_11 11 A11/2 
+* PWM_14 14 A14/2 
+* PWM_15 15 A15/2 
+* PWM_16 16 B0/2 
+* PWM_17 17 B1/2 
+* PWM_18 18 B2/2 
+* PWM_19 19 B3/2 
+* PWM_20 20 B4/2 
+* PWM_21 21 B5/2 
+* PWM_22 22 B6/2 
+* PWM_23 23 B7/2 
+* PWM_24 24 B8/2 
+* PWM_25 25 B9/2 
+* PWM_26 26 B10/2 
+* PWM_27 27 B11/2 
+* PWM_28 28 B12/2 
+* PWM_29 29 B13/2 
+* PWM_30 30 B14/2 
+* PWM_31 31 B15/2 
+
+## Unused Pinouts (spare as GPIO) for 'Robotics'
+
+| Pin | Mux0        | Mux1        | Mux2        | Mux3        |
+| --- | ----------- | ----------- | ----------- | ----------- |
+|  40 |             | C ULPI0_D4  |             |             |
+|  41 |             | C ULPI0_D5  |             |             |
+|  42 |             | C ULPI0_D6  |             |             |
+|  43 |             | C ULPI0_D7  |             |             |
+|  44 |             | C SPI0_CLK  |             |             |
+|  45 |             | C SPI0_NSS  |             |             |
+|  46 |             | C SPI0_MOSI |             |             |
+|  47 |             | C SPI0_MISO |             |             |
+|  58 |             | D UART0_TX  |             |             |
+|  59 |             | D UART0_RX  |             |             |
+|  60 |             | D TWI0_SDA  |             |             |
+|  61 |             | D TWI0_SCL  |             |             |
+|  62 |             | D UART1_TX  |             |             |
+|  63 |             | D UART1_RX  |             |             |
+
+# Reference Datasheets
+
+datasheets and pinout links
+
+* <http://datasheets.chipdb.org/AMD/8018x/80186/amd-80186.pdf>
+* <http://hands.com/~lkcl/eoma/shenzen/frida/FRD144A2701.pdf>
+* <http://pinouts.ru/Memory/sdcard_pinout.shtml>
+* p8 <http://www.onfi.org/~/media/onfi/specs/onfi_2_0_gold.pdf?la=en>
+* <https://www.heyrick.co.uk/blog/files/datasheets/dm9000aep.pdf>
+* <http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4393.pdf>
+* <https://www.nxp.com/docs/en/data-sheet/MCF54418.pdf>
+* ULPI OTG PHY, ST <http://www.st.com/en/interfaces-and-transceivers/stulpi01a.html>
+* ULPI OTG PHY, TI TUSB1210 <http://ti.com/product/TUSB1210/>
diff --git a/shakti/i_class/pinouts.py b/shakti/i_class/pinouts.py
new file mode 100644 (file)
index 0000000..c166639
--- /dev/null
@@ -0,0 +1,624 @@
+#!/usr/bin/env python
+
+from copy import deepcopy
+
+def pins(pingroup, bankspec, suffix, offs, bank, mux, spec=None, limit=None):
+    res = {}
+    names = {}
+    idx = 0
+    for name in pingroup[:limit]:
+        if suffix:
+            name_ = "%s_%s" % (name, suffix)
+        else:
+            name_ = name
+        if spec and spec.has_key(name):
+            continue
+        pin = {mux: (name_, bank)}
+        offs_bank, offs_ = offs
+        idx_ = offs_ + idx
+        idx += 1
+        idx_ += bankspec[bank]
+        res[idx_] = pin
+        names[name] = idx_
+    for name in pingroup:
+        if suffix:
+            name_ = "%s_%s" % (name, suffix)
+        else:
+            name_ = name
+        if not spec:
+            continue
+        if not spec.has_key(name):
+            continue
+        idx_, mux_, bank_ = spec[name]
+        idx_ = names[idx_]
+        #idx_ += bankspec[bank_]
+        pin = {mux_: (name_, bank_)}
+        if res.has_key(idx_):
+            res[idx_].update(pin)
+        else:
+            res[idx_] = pin
+    return res
+
+def i2s(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
+    i2spins = ['IISMCK', 'IISBCK', 'IISLRCK', 'IISDI']
+    for i in range(4):
+        i2spins.append("IISDO%d" % i)
+    return pins(i2spins, bankspec, suffix, offs, bank, mux, spec, limit)
+
+def emmc(bankspec, suffix, offs, bank, mux=1, spec=None):
+    emmcpins = ['MMCCMD', 'MMCCLK']
+    for i in range(8):
+        emmcpins.append("MMCD%d" % i)
+    return pins(emmcpins, bankspec, suffix, offs, bank, mux, spec)
+
+def sdmmc(bankspec, suffix, offs, bank, mux=1, spec=None,
+                start=None, limit=None):
+    sdmmcpins = ['CMD', 'CLK']
+    for i in range(4):
+        sdmmcpins.append("D%d" % i)
+    sdmmcpins = sdmmcpins[start:limit]
+    sdmmcpins = namesuffix('SD', suffix, sdmmcpins)
+    return pins(sdmmcpins, bankspec, '', offs, bank, mux, spec)
+
+def spi(bankspec, suffix, offs, bank, mux=1, spec=None):
+    spipins = namesuffix('SPI', suffix,
+                ['CLK', 'NSS', 'MOSI', 'MISO', 'NSS'])
+    return pins(spipins, bankspec, '', offs, bank, mux, spec)
+
+def quadspi(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
+    spipins = namesuffix('SPI', suffix,
+                ['CK', 'NSS', 'IO0', 'IO1', 'IO2', 'IO3'])
+    return pins(spipins, bankspec, '', offs, bank, mux, spec, limit)
+
+def i2c(bankspec, suffix, offs, bank, mux=1, spec=None):
+    spipins = namesuffix('TWI', suffix,
+                ['SDA', 'SCL'])
+    return pins(spipins, bankspec, '', offs, bank, mux, spec)
+
+def jtag(bankspec, suffix, offs, bank, mux=1, spec=None):
+    uartpins = namesuffix('JTAG', suffix, ['MS', 'DI', 'DO', 'CK'])
+    return pins(uartpins, bankspec, '', offs, bank, mux, spec)
+
+def uart(bankspec, suffix, offs, bank, mux=1, spec=None):
+    uartpins = namesuffix('UART', suffix, ['TX', 'RX'])
+    return pins(uartpins, bankspec, '', offs, bank, mux, spec)
+
+def namesuffix(name, suffix, namelist):
+    names = []
+    for n in namelist:
+        names.append("%s%s_%s" % (name, suffix, n))
+    return names
+
+def ulpi(bankspec, suffix, offs, bank, mux=1, spec=None):
+    ulpipins = namesuffix('ULPI', suffix, ['CK', 'DIR', 'STP', 'NXT'])
+    for i in range(8):
+        ulpipins.append('ULPI%s_D%d' % (suffix, i))
+    return pins(ulpipins, bankspec, "", offs, bank, mux, spec)
+
+def uartfull(bankspec, suffix, offs, bank, mux=1, spec=None):
+    uartpins = namesuffix('UART', suffix, ['TX', 'RX', 'CTS', 'RTS'])
+    return pins(uartpins, bankspec, '', offs, bank, mux, spec)
+
+def rgbttl(bankspec, suffix, offs, bank, mux=1, spec=None):
+    ttlpins = ['LCDCK', 'LCDDE', 'LCDHS', 'LCDVS']
+    for i in range(24):
+        ttlpins.append("LCD%d" % i)
+    return pins(ttlpins, bankspec, suffix, offs, bank, mux, spec)
+
+def rgmii(bankspec, suffix, offs, bank, mux=1, spec=None):
+    buspins = []
+    for i in range(4):
+        buspins.append("RG_ERXD%d" % i)
+    for i in range(4):
+        buspins.append("RG_ETXD%d" % i)
+    for i in range(2):
+        buspins.append("RG_FB_CS%d" % i)
+    buspins += ['RG_ERXCK', 'RG_ERXERR', 'RG_ERXDV',
+                'RG_EMDC', 'RG_EMDIO',
+                'RG_ETXEN', 'RG_ETXCK', 'RG_ECRS',
+                'RG_ECOL', 'RG_ETXERR']
+    return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
+
+def flexbus1(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
+    buspins = []
+    for i in range(8):
+        buspins.append("FB_AD%d" % i)
+    for i in range(2):
+        buspins.append("FB_CS%d" % i)
+    buspins += ['FB_ALE', 'FB_OE', 'FB_RW', 'FB_TA', 'FB_CLK',
+                'FB_A0', 'FB_A1', 'FB_TS', 'FB_TBST',
+                'FB_TSIZ0', 'FB_TSIZ1']
+    for i in range(4):
+        buspins.append("FB_BWE%d" % i)
+    for i in range(2,6):
+        buspins.append("FB_CS%d" % i)
+    return pins(buspins, bankspec, suffix, offs, bank, mux, spec, limit)
+
+def flexbus2(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
+    buspins = []
+    for i in range(8,32):
+        buspins.append("FB_AD%d" % i)
+    return pins(buspins, bankspec, suffix, offs, bank, mux, spec, limit)
+
+def mcu8080(bankspec, suffix, offs, bank, mux=1, spec=None):
+    buspins = []
+    for i in range(8):
+        buspins.append("MCUD%d" % i)
+    for i in range(8):
+        buspins.append("MCUAD%d" % (i+8))
+    for i in range(6):
+        buspins.append("MCUCS%d" % i)
+    for i in range(2):
+        buspins.append("MCUNRB%d" % i)
+    buspins += ['MCUCD', 'MCURD', 'MCUWR', 'MCUCLE', 'MCUALE',
+                'MCURST']
+    return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
+
+def _pinbank(bankspec, prefix, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
+    gpiopins = []
+    for i in range(gpiooffs, gpiooffs+gpionum):
+        gpiopins.append("%s%s%d" % (prefix, bank, i))
+    return pins(gpiopins, bankspec, suffix, offs, bank, mux, spec)
+
+def eint(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
+    gpiopins = []
+    for i in range(gpiooffs, gpiooffs+gpionum):
+        gpiopins.append("EINT%d" % (i))
+    return pins(gpiopins, bankspec, suffix, offs, bank, mux, spec)
+
+def pwm(bankspec, suffix, offs, bank, mux=1, spec=None):
+    return pins(['PWM', ], bankspec, suffix, offs, bank, mux, spec)
+
+def gpio(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
+    return _pinbank(bankspec, "GPIO", suffix, offs, bank, gpiooffs,
+                              gpionum, mux=0, spec=None)
+
+def display(pins):
+    print "| Pin | Mux0        | Mux1        | Mux2        | Mux3        |"
+    print "| --- | ----------- | ----------- | ----------- | ----------- |"
+    pinidx = pins.keys()
+    pinidx.sort()
+    for pin in pinidx:
+        pdata = pins[pin]
+        res = '| %3d |' % pin
+        for mux in range(4):
+            if not pdata.has_key(mux):
+                res += "             |"
+                continue
+            name, bank = pdata[mux]
+            res += " %s %-9s |" % (bank, name)
+        print res
+
+def fnsplit(f):
+    a = ''
+    n = 0
+    if not f.startswith('FB_'):
+        f2 = f.split('_')
+        if len(f2) == 2:
+            if f2[1].isdigit():
+                return f2[0], int(f2[1])
+            return f2[0], f2[1]
+    #print f
+    while f and not f[0].isdigit():
+        a += f[0]
+        f = f[1:]
+    return a, int(f) if f else None
+
+def fnsort(f1, f2):
+    a1, n1 = fnsplit(f1)
+    a2, n2 = fnsplit(f2)
+    x = cmp(a1, a2)
+    if x != 0:
+        return x
+    return cmp(n1, n2)
+    
+def find_fn(fname, names):
+    for n in names:
+        if fname.startswith(n):
+            return n
+
+def display_fns(bankspec, pins, function_names):
+    fn_names = function_names.keys()
+    fns = {}
+    for (pin, pdata) in pins.items():
+        for mux in range(1,4): # skip GPIO for now
+            if not pdata.has_key(mux):
+                continue
+            name, bank = pdata[mux]
+            if not fns.has_key(name):
+                fns[name] = []
+            fns[name].append((pin-bankspec[bank], mux, bank))
+
+    fnidx = fns.keys()
+    fnidx.sort(fnsort)
+    current_fn = None
+    for fname in fnidx:
+        fnbase = find_fn(fname, fn_names)
+        #print "name", fname
+        if fnbase != current_fn:
+            if current_fn is not None:
+                print
+            print "## %s" % fnbase
+            print
+            print function_names[fnbase]
+            print
+            current_fn = fnbase
+        print "* %-9s :" % fname,
+        for (pin, mux, bank) in fns[fname]:
+            print "%s%d/%d" % (bank, pin, mux),
+        print
+
+    return fns
+
+def check_functions(title, bankspec, fns, pins, required, eint, pwm,
+                    descriptions=None):
+    fns = deepcopy(fns)
+    pins = deepcopy(pins)
+    if descriptions is None:
+        descriptions = {}
+
+    print "# Pinmap for %s" % title
+    print
+
+
+    for name in required:
+        print "## %s" % name
+        print
+        if descriptions and descriptions.has_key(name):
+            print descriptions[name]
+            print
+
+        name = name.split(':')
+        if len(name) == 2:
+            findbank = name[0][0]
+            findmux = int(name[0][1:])
+            name = name[1]
+        else:
+            name = name[0]
+            findbank = None
+            findmux = None
+        name = name.split('/')
+        if len(name) == 2:
+            count = int(name[1])
+        else:
+            count = 100000
+        name = name[0]
+        found = set()
+        fnidx = fns.keys()
+        #fnidx.sort(fnsort)
+        pinfound = {}
+        for fname in fnidx:
+            if not fname.startswith(name):
+                continue
+            for pin, mux, bank in fns[fname]:
+                if findbank is not None:
+                    if findbank != bank:
+                        continue
+                    if findmux != mux:
+                        continue
+                pin_ = pin + bankspec[bank]
+                if pins.has_key(pin_):
+                    pinfound[pin_] = (fname, pin_, bank, pin, mux)
+
+        pinidx = pinfound.keys()
+        pinidx.sort()
+
+        for pin_ in pinidx:
+            fname, pin_, bank, pin, mux = pinfound[pin_]
+            if fname in found:
+                continue
+            found.add(fname)
+            if len(found) > count:
+                continue
+            del pins[pin_]
+            print "* %s %d %s%d/%d" % (fname, pin_, bank, pin, mux)
+
+        print
+
+    # gpios
+    gpios = []
+    for name in descriptions.keys():
+        if not name.startswith('GPIO'):
+            continue
+        if name == 'GPIO':
+            continue
+        gpios.append(name)
+    gpios.sort()
+    
+    if gpios:
+        print "## GPIO"
+        print
+
+        for fname in gpios:
+            if fname in found:
+                continue
+            desc = ''
+            if descriptions and descriptions.has_key(fname):
+                desc = ': %s' % descriptions[fname]
+            bank = fname[4]
+            pin = int(fname[5:])
+            pin_ = pin + bankspec[bank]
+            if not pins.has_key(pin_):
+                continue
+            del pins[pin_]
+            found.add(fname)
+            print "* %-8s %d %s%-2d %s" % (fname, pin_, bank, pin, desc)
+        print
+
+    if eint:
+        display_group("EINT", eint, fns, pins, descriptions)
+    if pwm:
+        display_group("PWM", pwm, fns, pins, descriptions)
+
+    print "## Unused Pinouts (spare as GPIO) for '%s'" % title
+    print
+    if descriptions and descriptions.has_key('GPIO'):
+        print descriptions['GPIO']
+        print 
+    display(pins)
+    print
+
+    return pins # unused
+
+def display_group(title, todisplay, fns, pins, descriptions):
+    print "## %s" % title
+    print
+
+    found = set()
+    for fname in todisplay:
+        desc = ''
+        if descriptions and descriptions.has_key(fname):
+            desc = ': %s' % descriptions[fname]
+        fname = fname.split(':')
+        if len(fname) == 2:
+            findbank = fname[0][0]
+            findmux = int(fname[0][1:])
+            fname = fname[1]
+        else:
+            fname = fname[0]
+            findbank = None
+            findmux = None
+        for (pin, mux, bank) in fns[fname]:
+            if findbank is not None:
+                if findbank != bank:
+                    continue
+                if findmux != mux:
+                    continue
+            if fname in found:
+                continue
+            pin_ = pin + bankspec[bank]
+            if not pins.has_key(pin_):
+                continue
+            del pins[pin_]
+            found.add(fname)
+            print "* %s %d %s%d/%d %s" % (fname, pin_, bank, pin, mux, desc)
+    print
+
+def pinmerge(pins, fn):
+    for (pinidx, v) in fn.items():
+        if not pins.has_key(pinidx):
+            pins[pinidx] = v
+            continue
+        pins[pinidx].update(v)
+
+def display_fixed(fixed, offs):
+
+    fkeys = fixed.keys()
+    fkeys.sort()
+    pin_ = offs
+    for pin, k in enumerate(fkeys):
+        print "## %s" % k
+        print
+        prevname = ''
+        linecount = 0
+        for name in fixed[k]:
+            if linecount == 4:
+                linecount = 0
+                print
+            if prevname[:2] == name[:2] and linecount != 0:
+                print name,
+                linecount += 1
+            else:
+                if linecount != 0:
+                    print
+                print "* %d: %d %s" % (pin_, pin, name),
+                linecount = 1
+            prevname = name
+            pin_ += 1
+        if linecount != 0:
+            print
+        print
+
+if __name__ == '__main__':
+    pinouts = {}
+
+    pinbanks = {'A': 16,
+                'B': 16,
+                'C': 16,
+                'D': 16,
+                'E': 48,
+              }
+    bankspec = {}
+    pkeys = pinbanks.keys()
+    pkeys.sort()
+    offs = 0
+    for kn in pkeys:
+        bankspec[kn] = offs
+        offs += pinbanks[kn]
+
+    # Bank A, 0-15
+    pinmerge(pinouts, gpio(bankspec, "", ('A', 0), "A", 0, 16, 0))
+    pinmerge(pinouts, spi(bankspec, "0", ('A', 0), "A", 1))
+    pinmerge(pinouts, spi(bankspec, "1", ('A', 4), "A", 1))
+    pinmerge(pinouts, uart(bankspec, "0", ('A', 8), "A", 1))
+    pinmerge(pinouts, uart(bankspec, "1", ('A', 10), "A", 1))
+    pinmerge(pinouts, i2c(bankspec, "0", ('A', 12), "A", 1))
+    pinmerge(pinouts, i2c(bankspec, "1", ('A', 14), "A", 1))
+    for i in range(16):
+        pinmerge(pinouts, pwm(bankspec, str(i), ('A', i), "A", mux=2))
+
+    # Bank B, 16-31
+    pinmerge(pinouts, gpio(bankspec, "", ('B', 0), "B", 0, 16, 0))
+    pinmerge(pinouts, spi(bankspec, "2", ('B', 0), "B", 1))
+    pinmerge(pinouts, uart(bankspec, "2", ('B', 4), "B", 1))
+    pinmerge(pinouts, uart(bankspec, "3", ('B', 6), "B", 1))
+    pinmerge(pinouts, uart(bankspec, "4", ('B', 8), "B", 1))
+    pinmerge(pinouts, i2c(bankspec, "2", ('B', 10), "B", 1))
+    pinmerge(pinouts, i2c(bankspec, "3", ('B', 12), "B", 1))
+    pinmerge(pinouts, uart(bankspec, "5", ('B', 14), "B", 1))
+    for i in range(16):
+        pinmerge(pinouts, pwm(bankspec, str(i+16), ('B', i), "B", mux=2))
+
+    # Bank C, 32-47
+    pinmerge(pinouts, ulpi(bankspec, "0", ('C', 0), "C", 1))
+    pinmerge(pinouts, spi(bankspec, "0", ('C', 12), "C", 1))
+
+    # Bank D, 48-64
+    pinmerge(pinouts, sdmmc(bankspec, "0", ('D', 0), "D", 1))
+    pinmerge(pinouts, jtag(bankspec, "0", ('D', 6), "D", 1))
+    pinmerge(pinouts, uart(bankspec, "0", ('D', 10), "D", 1))
+    pinmerge(pinouts, i2c(bankspec, "0", ('D', 12), "D", 1))
+    pinmerge(pinouts, uart(bankspec, "1", ('D', 14), "D", 1))
+
+    # Bank E, 64-111
+    flexspec = {
+        'FB_TS': ('FB_ALE', 2, "D"),
+        'FB_CS2': ('FB_BWE2', 2, "D"),
+        'FB_A0': ('FB_BWE2', 3, "D"),
+        'FB_CS3': ('FB_BWE3', 2, "D"),
+        'FB_A1': ('FB_BWE3', 3, "D"),
+        'FB_TBST': ('FB_OE', 2, "D"),
+        'FB_TSIZ0': ('FB_BWE0', 2, "D"),
+        'FB_TSIZ1': ('FB_BWE1', 2, "D"),
+    }
+    pinmerge(pinouts, flexbus1(bankspec, "", ('E', 0), "E", 1))
+    pinmerge(pinouts, flexbus2(bankspec, "", ('E', 30), "E", 1, limit=8))
+
+    print "# Pinouts (PinMux)"
+    print
+    print "auto-generated by [[pinouts.py]]"
+    print
+    print "[[!toc  ]]"
+    print
+    display(pinouts)
+    print
+
+    print "# Pinouts (Fixed function)"
+    print
+
+    fixedpins = {
+      'CTRL_SYS':
+        [
+        'TEST', 'BOOT_SEL', 
+        'NMI#', 'RESET#', 
+        'CLK24M_IN', 'CLK24M_OUT', 
+        'CLK32K_IN', 'CLK32K_OUT', 
+        'PLLTEST', 'PLLREGIO', 'PLLVP25', 
+        'PLLDV', 'PLLVREG', 'PLLGND', 
+       ],
+
+      'POWER_CPU':
+        ['VDD0_CPU', 'VDD1_CPU', 'VDD2_CPU', 'VDD3_CPU', 'VDD4_CPU', 'VDD5_CPU',
+         'GND0_CPU', 'GND1_CPU', 'GND2_CPU', 'GND3_CPU', 'GND4_CPU', 'GND5_CPU',
+        ],
+
+      'POWER_DLL':
+        ['VDD0_DLL', 'VDD1_DLL', 'VDD2_DLL', 
+         'GND0_DLL', 'GND1_DLL', 'GND2_DLL', 
+        ],
+
+      'POWER_INT':
+        ['VDD0_INT', 'VDD1_INT', 'VDD2_INT', 'VDD3_INT', 'VDD4_INT', 
+         'VDD5_INT', 'VDD6_INT', 'VDD7_INT', 'VDD8_INT', 'VDD9_INT', 
+         'GND0_INT', 'GND1_INT', 'GND2_INT', 'GND3_INT', 'GND4_INT', 
+         'GND5_INT', 'GND6_INT', 'GND7_INT', 'GND8_INT', 'GND9_INT', 
+        ],
+
+      'POWER_GPIO':
+        ['VDD_GPIOA', 'VDD_GPIOB', 'VDD_GPIOC', 'VDD_GPIOD', 'VDD_GPIOE',
+         'GND_GPIOA', 'GND_GPIOB', 'GND_GPIOC', 'GND_GPIOD', 'GND_GPIOE',
+        ]
+
+      }
+
+    display_fixed(fixedpins, len(pinouts))
+
+    print "# Functions (PinMux)"
+    print
+    print "auto-generated by [[pinouts.py]]"
+    print
+
+    function_names = {'EINT': 'External Interrupt',
+                      'FB': 'MC68k FlexBus',
+                      'IIS': 'I2S Audio',
+                      'JTAG0': 'JTAG',
+                      'JTAG1': 'JTAG (same as JTAG2, JTAG_SEL=LOW)',
+                      'JTAG2': 'JTAG (same as JTAG1, JTAG_SEL=HIGH)',
+                      'LCD': '24-pin RGB/TTL LCD',
+                      'RG': 'RGMII Ethernet',
+                      'MMC': 'eMMC 1/2/4/8 pin',
+                      'PWM': 'PWM (pulse-width modulation)',
+                      'SD0': 'SD/MMC 0',
+                      'SD1': 'SD/MMC 1',
+                      'SD2': 'SD/MMC 2',
+                      'SD3': 'SD/MMC 3',
+                      'SPI0': 'SPI (Serial Peripheral Interface) 0',
+                      'SPI1': 'SPI (Serial Peripheral Interface) 1',
+                      'SPI2': 'SPI (Serial Peripheral Interface) 2',
+                      'SPI3': 'Quad SPI (Serial Peripheral Interface) 3',
+                      'TWI0': 'I2C 0',
+                      'TWI1': 'I2C 1',
+                      'TWI2': 'I2C 2',
+                      'TWI3': 'I2C 3',
+                      'UART0': 'UART (TX/RX) 0',
+                      'UART1': 'UART (TX/RX) 1',
+                      'UART2': 'UART (TX/RX) 2',
+                      'UART3': 'UART (TX/RX) 3',
+                      'UART4': 'UART (TX/RX) 4',
+                      'UART5': 'UART (TX/RX) 5',
+                      'ULPI0': 'ULPI (USB Low Pin-count) 0',
+                      'ULPI1': 'ULPI (USB Low Pin-count) 1',
+                      'ULPI2': 'ULPI (USB Low Pin-count) 2',
+                      'ULPI3': 'ULPI (USB Low Pin-count) 3',
+                    }
+            
+    fns = display_fns(bankspec, pinouts, function_names)
+    print
+
+    # Scenarios below can be spec'd out as either "find first interface"
+    # by name/number e.g. SPI1, or as "find in bank/mux" which must be
+    # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
+    # EINT and PWM are grouped together, specially, but may still be spec'd
+    # using "BM:Name".  Pins are removed in-order as listed from
+    # lists (interfaces, EINTs, PWMs) from available pins.
+
+    # Robotics scenario.  
+
+    robotics = ['FB', 'ULPI0/8', 
+                'SD0',
+                'JTAG0', 'UART0', 
+              'SPI0', 'TWI0']
+    robotics_pwm = []
+    for i in range(32):
+        robotics_pwm.append('PWM_%d' % i)
+    robotics_eint = ['EINT24', 'EINT25', 'EINT26', 'EINT27',
+                       'EINT20', 'EINT21', 'EINT22', 'EINT23']
+    robotics_eint = []
+
+    unused_pins = check_functions("Robotics", bankspec, fns, pinouts,
+                 robotics, robotics_eint, robotics_pwm)
+
+    print "# Reference Datasheets"
+    print
+    print "datasheets and pinout links"
+    print
+    print "* <http://datasheets.chipdb.org/AMD/8018x/80186/amd-80186.pdf>"
+    print "* <http://hands.com/~lkcl/eoma/shenzen/frida/FRD144A2701.pdf>"
+    print "* <http://pinouts.ru/Memory/sdcard_pinout.shtml>"
+    print "* p8 <http://www.onfi.org/~/media/onfi/specs/onfi_2_0_gold.pdf?la=en>"
+    print "* <https://www.heyrick.co.uk/blog/files/datasheets/dm9000aep.pdf>"
+    print "* <http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4393.pdf>"
+    print "* <https://www.nxp.com/docs/en/data-sheet/MCF54418.pdf>"
+    print "* ULPI OTG PHY, ST <http://www.st.com/en/interfaces-and-transceivers/stulpi01a.html>"
+    print "* ULPI OTG PHY, TI TUSB1210 <http://ti.com/product/TUSB1210/>"
+