fanfansym - KiCad Parts Symbol Generator

# はじめに
KiCadはフリーの素晴らしいPCB CADです。
多くのパーツがLibraryとして公開されていますが、たまたま自分が使いたいものがまだ登録されていないと、自分で作らねばなりません。
これが大きな手間で時に基板自身を書くのより、ライブラリー登録に時間がかかったりします。
特にピン数が多く、複数の機能を兼用したピンが多い、CPUではその労力はとても大きなものです。

# fanfansym.py
そこで少しでもこの手間を軽減するためにfanfansym.pyというPython programを書きました。

- LSI のpin割り当て表からpin名とpin 番号、Pinの属性を書きだす。
- fanfansym.py にこのファイルを食わす。
- \<parts-name>.kicad_sym を出力するので、KiCadでこれをimportする。
- シンボルエディターでシェープを整えるなど、仕上げをする。

以上で新パーツの登録ができます。
なお、KiCad SymbolからFanfansymは入力可能なTextを取り出す[Diskisym](https://qiita.com/maclineto/items/1da8553b1eaa534122d8?fbclid=IwAR1km0gWXMoWbJO_vj7mbM-jnx8qzx5DFvN-K_V5oIgjUi1QGhd2G3qum1s)もあります。
では、実際の操作を見ていきましょう。
# 動作環境
- Python 3
- KiCad 6
# pin assignを書きだす。
LSIのPDF仕様書などからCopy & Pasteするとか、Python PyPDF2を使うなどしてPin名称を切り出します。
当面pins.tetというファイル名固定です。
最初の行は
```
#parts名
次からは
[pin name]
@[number] [pin mode]
と書き並べます。
[name1]
[name2]
と書くと
name1/name2 と並びます。
```
空行は任意の箇所に見やすくするために入れられます。

pin modeは
``` python
dictkind = {
"c": 'open_collector','open_collector': 'open_collector',
"e": 'open_emittor','open_emittor': 'open_emittor',
"n": 'no_connect','no_connect': 'no_connect',
"o": 'output','output': 'output',
"i": 'input','input':'input',
"b": 'bidirectional','bidirectional':'bidirectional',
"t": 'tri_state','tri_state':'tri_state',
"pi": 'power_in','power_in':'power_in',
"po": 'power_out','power_out':'power_out',
"u": 'unspecified','unspecified':'unspecified',
"f": 'free','free':'free',
"p": 'passive','passive':'passive',
"u": 'unspecified','unspecified':'unspecified',
}
```
と定義されてます。
c,o,iなどの略号で指定できますし、open_collector,output,input等フルスペリングも可能です。

``` text: spins.txt
#CY9B560L

VCC 
@1 pi

P50 
AIN0_0 
INT00_0 
TIOA0_0 
CTS4_0 
@2 b

P51 
BIN0_0 
INT01_0 
TIOB0_0 
RTS4_0 
@3 b

P52 
IC00_0 
ZIN0_0 
INT02_0 
TIOA1_0 
SIN4_0 
@4 b

P53 
IC01_0 
INT03_0 
TIOB1_0 
@5 b

P54 
IC02_0 
INT04_0 
TIOA2_0 
SCK4_0 
@6 b

P55 
IC03_0 
INT05_0 
TIOB2_0 
SIN3_0 
@7 b

P56 
FRCK0_0 
INT06_0 
TIOA3_0 
SOT3_0 
@8 b

P57 
DTTI0X_0 
INT07_0 
TIOB3_0 
SCK3_0 
ADTG_0 
@9 b

P30 
RTO00_0 
AIN0_1 
INT08_0 
TIOA4_0 
SIN2_0 
@10 b

P31 
RTO01_0 
BIN0_1 
INT09_0 
TIOB4_0 
SOT2_0 
@11 b

P32 
RTO02_0 
ZIN0_1 
INT10_0 
TIOA5_0 
SCK2_0 
@12  b

P33 
RTO03_0 
INT11_0 
TIOB5_0 
SIN4_1 
@13 b

P34 
RTO04_0 
INT12_0 
TIOA6_0 
SOT4_1 
@14 b

P35 
WKUP2 
RTO05_0 
INT13_0 
TIOB6_0 
SCK4_1 
@15 b

VSS 
@16 pi

```

# Python program
これを書きプログラムに食わせます。
```python: fanfansym.py
pinfile = 'fanfan.pintext'
# Fanfansym.py: Symbol generator for KiCad6
# Written in Python 3
# Copyright (c) 2022 Fanfan
# Lisence: MIT
import re
seqat = re.compile(r'@\d+')
seqsharp = re.compile(r'#[A-Za-z0-9_\-]+')
seqbl = re.compile(r'^ *$')
seqnum = re.compile(r'\d+')
letters = re.compile(r'[A-Za-z0-9_\-]+')
seqmode = re.compile(r'[a-z_]+')

dictkind = {
"c": 'open_collector','open_collector': 'open_collector',
"e": 'open_emittor','open_emittor': 'open_emittor',
"n": 'no_connect','no_connect': 'no_connect',
"o": 'output','output': 'output',
"i": 'input','input':'input',
"b": 'bidirectional','bidirectional':'bidirectional',
"t": 'tri_state','tri_state':'tri_state',
"pi": 'power_in','power_in':'power_in',
"po": 'power_out','power_out':'power_out',
"u": 'unspecified','unspecified':'unspecified',
"f": 'free','free':'free',
"p": 'passive','passive':'passive',
"u": 'unspecified','unspecified':'unspecified',
}
header = '''
(kicad_symbol_lib (version 20211014) (generator kicad_fanfan_lib_gen)
(symbol "%s" (in_bom yes) (on_board yes)
(property "Reference" "U" (id 0) (at 0 2.54 0)
    (effects (font (size 1.27 1.27)))
)
(property "Value" "%s" (id 1) (at 0 0 0)
    (effects (font (size 1.27 1.27)))
)
(property "Footprint" "" (id 2) (at 0 0 0)
    (effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 0 0 0)
    (effects (font (size 1.27 1.27)) hide)
)
(property "ki_locked" "" (id 4) (at 0 0 0)
    (effects (font (size 1.27 1.27)))
)
(symbol "%s_1_1"
'''

cont = ''
fpin = open(pinfile,"r")
line = fpin.readline()
list = re.findall(seqsharp,line)
parts = list[0].replace('#','')
fout = open(parts+'.kicad_sym',"w")
fout.write(header % (parts,parts,parts))
name=''
ypos = -2.54
while True:
    line = fpin.readline()
    if len(line) == 0:
        break
    if re.search(seqat,line):
        num = re.findall(seqnum,line)[0]
        mmode = re.findall(seqmode,line)
        if len(mmode) == 0:
            mode = 'no_connect'
        else:
            mode = dictkind[mmode[0]]
        name = cont.replace('/','',1)
        pin = '''(pin %s line (at 0 %.2f 0) (length 2.54)\n
        (name "%s" (effects (font (size 1.27 1.27))))\n
        (number "%s" (effects (font (size 1.27 1.27))))\n)
        '''
        fout.write(pin % (mode,ypos,name,num))
        cont = ""
        ypos -= 2.54
    else:
        line = re.findall(letters,line)
        if len(line) > 0:
            cont += '/' + line[0] 
fout.write(')))')
```
# KiCadによる読み込み
CY9B560L.kicad_symが生成されるのでKiCadで読み込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245853/7b3f816b-cfd1-02e5-e94d-f5849381545e.png)



正常に読み込めました。


ミラーリングしたり、枠を書いたりして使いやすく仕上げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245853/cdb7fc6a-0b6d-2552-cf19-3895d01a2d33.png)


# まとめ
あまり時間を取れないので、とりあえずAs is の公開です。