Updated BOM adding JLC part numbers, created MFG files, added python script that creates CPL file for JLC.
This commit is contained in:
parent
7cca9e7980
commit
2b8a26d897
|
@ -24,6 +24,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "ST,STPS2H100UY" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,497-11093-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C157420" H 5025 6475 50 0001 C CNN "LCSC"
|
||||
1 5025 6475
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -53,6 +54,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 10675 3100 50 0001 C CNN "LCSC"
|
||||
1 10675 3100
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -67,6 +69,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 11975 2575 50 0001 C CNN "LCSC"
|
||||
1 11975 2575
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -219,6 +222,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "ST,STPS2H100UY" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,497-11093-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C157420" H 11000 3900 50 0001 C CNN "LCSC"
|
||||
1 11000 3900
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -235,6 +239,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 10675 4300 50 0001 C CNN "LCSC"
|
||||
1 10675 4300
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -331,6 +336,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "ST,STPS2H100UY" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,497-11093-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C157420" H 12300 4450 50 0001 C CNN "LCSC"
|
||||
1 12300 4450
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -347,6 +353,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 11975 4850 50 0001 C CNN "LCSC"
|
||||
1 11975 4850
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -447,6 +454,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 5975 6000 50 0001 C CNN "LCSC"
|
||||
1 5975 6000
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -461,6 +469,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 10750 6650 50 0001 C CNN "LCSC"
|
||||
1 10750 6650
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -607,6 +616,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "KEMET,C0805C224M1RACTU" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,399-9205-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "" H 11975 7125 50 0001 C CNN "LCSC"
|
||||
1 11975 7125
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -621,6 +631,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "KEMET,C0805C224M1RACTU" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,399-9205-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "" H 12375 7125 50 0001 C CNN "LCSC"
|
||||
1 12375 7125
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -677,6 +688,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "KEMET,C0805C224M1RACTU" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,399-9205-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C5378" H 10600 6200 50 0001 C CNN "LCSC"
|
||||
1 10600 6200
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -713,6 +725,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "KEMET,C0805C224M1RACTU" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,399-9205-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C5378" H 9900 6200 50 0001 C CNN "LCSC"
|
||||
1 9900 6200
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -783,6 +796,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 5975 7000 50 0001 C CNN "LCSC"
|
||||
1 5975 7000
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -883,6 +897,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "ST,STPS2H100UY" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,497-11093-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C157420" H 5350 6400 50 0001 C CNN "LCSC"
|
||||
1 5350 6400
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -1447,6 +1462,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 5875 3100 50 0001 C CNN "LCSC"
|
||||
1 5875 3100
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -1461,6 +1477,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 4575 2575 50 0001 C CNN "LCSC"
|
||||
1 4575 2575
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -1602,6 +1619,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "ST,STPS2H100UY" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,497-11093-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C157420" H 5550 3900 50 0001 C CNN "LCSC"
|
||||
1 5550 3900
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -1618,6 +1636,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 5875 4300 50 0001 C CNN "LCSC"
|
||||
1 5875 4300
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -1716,6 +1735,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "Nexperia,BUK9230-100B" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,1727-4708-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C194346" H 4575 4850 50 0001 C CNN "LCSC"
|
||||
1 4575 4850
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
|
@ -2071,6 +2091,7 @@ F 3 "" H 12525 3500 50 0001 C CNN
|
|||
F 4 "Diodes,SBR10200CTL-13" H 12525 3500 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,SBR10200CTL-13DICT-ND" H 12525 3500 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 12525 3500 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C135494" H 12525 3500 50 0001 C CNN "LCSC"
|
||||
1 12525 3500
|
||||
0 1 -1 0
|
||||
$EndComp
|
||||
|
@ -2085,6 +2106,7 @@ F 3 "" H 3950 3500 50 0001 C CNN
|
|||
F 4 "Diodes,SBR10200CTL-13" H 3950 3500 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,SBR10200CTL-13DICT-ND" H 3950 3500 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 3950 3500 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C135494" H 3950 3500 50 0001 C CNN "LCSC"
|
||||
1 3950 3500
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
|
@ -2729,6 +2751,7 @@ F 3 "" H 7325 3975 60 0001 C CNN
|
|||
F 4 "ST,STPS2H100UY" V 3805 3950 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 "DIGI,497-11093-1-ND" V 3805 3950 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 7325 3975 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C157420" H 4250 4450 50 0001 C CNN "LCSC"
|
||||
1 4250 4450
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3083,6 +3106,7 @@ F 3 "" H 13000 2325 60 0001 C CNN
|
|||
F 4 " , " V 9480 2300 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 9480 2300 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 13000 2325 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 10700 925 50 0001 C CNN "LCSC"
|
||||
1 10700 925
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3113,6 +3137,7 @@ F 3 "" H 13000 2225 60 0001 C CNN
|
|||
F 4 " , " V 9480 2200 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 9480 2200 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 13000 2225 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 10700 825 50 0001 C CNN "LCSC"
|
||||
1 10700 825
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3143,6 +3168,7 @@ F 3 "" H 13000 2425 60 0001 C CNN
|
|||
F 4 " , " V 9480 2400 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 9480 2400 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 13000 2425 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 10700 1025 50 0001 C CNN "LCSC"
|
||||
1 10700 1025
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3173,6 +3199,7 @@ F 3 "" H 13000 2625 60 0001 C CNN
|
|||
F 4 " , " V 9480 2600 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 9480 2600 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 13000 2625 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 10700 1225 50 0001 C CNN "LCSC"
|
||||
1 10700 1225
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3203,6 +3230,7 @@ F 3 "" H 8100 2225 60 0001 C CNN
|
|||
F 4 " , " V 4580 2200 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2200 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2225 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 825 50 0001 C CNN "LCSC"
|
||||
1 5800 825
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3233,6 +3261,7 @@ F 3 "" H 8100 2125 60 0001 C CNN
|
|||
F 4 " , " V 4580 2100 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2100 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2125 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 725 50 0001 C CNN "LCSC"
|
||||
1 5800 725
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3263,6 +3292,7 @@ F 3 "" H 8100 2425 60 0001 C CNN
|
|||
F 4 " , " V 4580 2400 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2400 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2425 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 1025 50 0001 C CNN "LCSC"
|
||||
1 5800 1025
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3293,6 +3323,7 @@ F 3 "" H 8100 2325 60 0001 C CNN
|
|||
F 4 " , " V 4580 2300 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2300 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2325 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 925 50 0001 C CNN "LCSC"
|
||||
1 5800 925
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3323,6 +3354,7 @@ F 3 "" H 8100 2525 60 0001 C CNN
|
|||
F 4 " , " V 4580 2500 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2500 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2525 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 1125 50 0001 C CNN "LCSC"
|
||||
1 5800 1125
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3353,6 +3385,7 @@ F 3 "" H 8100 2625 60 0001 C CNN
|
|||
F 4 " , " V 4580 2600 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2600 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2625 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 1225 50 0001 C CNN "LCSC"
|
||||
1 5800 1225
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3383,6 +3416,7 @@ F 3 "" H 8100 2725 60 0001 C CNN
|
|||
F 4 " , " V 4580 2700 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2700 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2725 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 1325 50 0001 C CNN "LCSC"
|
||||
1 5800 1325
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3413,6 +3447,7 @@ F 3 "" H 8100 2825 60 0001 C CNN
|
|||
F 4 " , " V 4580 2800 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 4580 2800 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 8100 2825 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 5800 1425 50 0001 C CNN "LCSC"
|
||||
1 5800 1425
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3443,6 +3478,7 @@ F 3 "" H 11125 2125 60 0001 C CNN
|
|||
F 4 " , " V 7605 2100 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 7605 2100 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 11125 2125 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 8825 725 50 0001 C CNN "LCSC"
|
||||
1 8825 725
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3482,6 +3518,7 @@ F 3 "" H 10000 2125 60 0001 C CNN
|
|||
F 4 " , " V 6480 2100 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 6480 2100 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 10000 2125 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 7700 725 50 0001 C CNN "LCSC"
|
||||
1 7700 725
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3523,6 +3560,7 @@ F 3 "" H 11125 2225 60 0001 C CNN
|
|||
F 4 " , " V 7605 2200 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 7605 2200 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 11125 2225 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 8825 825 50 0001 C CNN "LCSC"
|
||||
1 8825 825
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3616,6 +3654,7 @@ F 3 "" H 11125 2325 60 0001 C CNN
|
|||
F 4 " , " V 7605 2300 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 7605 2300 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 11125 2325 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 8825 925 50 0001 C CNN "LCSC"
|
||||
1 8825 925
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3644,6 +3683,7 @@ F 3 "" H 11125 2425 60 0001 C CNN
|
|||
F 4 " , " V 7605 2400 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 7605 2400 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 11125 2425 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 8825 1025 50 0001 C CNN "LCSC"
|
||||
1 8825 1025
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3672,6 +3712,7 @@ F 3 "" H 11125 2525 60 0001 C CNN
|
|||
F 4 " , " V 7605 2500 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 7605 2500 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 11125 2525 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 8825 1125 50 0001 C CNN "LCSC"
|
||||
1 8825 1125
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3700,6 +3741,7 @@ F 3 "" H 11125 2625 60 0001 C CNN
|
|||
F 4 " , " V 7605 2600 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 7605 2600 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 11125 2625 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 8825 1225 50 0001 C CNN "LCSC"
|
||||
1 8825 1225
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
|
@ -3736,6 +3778,7 @@ F 3 "" H 15150 7250 60 0001 C CNN
|
|||
F 4 " , " V 11630 7225 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 11630 7225 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 15150 7250 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 12850 5850 50 0001 C CNN "LCSC"
|
||||
1 12850 5850
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3881,6 +3924,7 @@ F 3 "" H 15300 2400 60 0001 C CNN
|
|||
F 4 " , " V 11780 2375 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 11780 2375 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 15300 2400 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 13000 1000 50 0001 C CNN "LCSC"
|
||||
1 13000 1000
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3909,6 +3953,7 @@ F 3 "" H 15300 2125 60 0001 C CNN
|
|||
F 4 " , " V 11780 2100 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 11780 2100 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 15300 2125 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 13000 725 50 0001 C CNN "LCSC"
|
||||
1 13000 725
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
@ -3948,6 +3993,7 @@ F 3 "" H 15300 2500 60 0001 C CNN
|
|||
F 4 " , " V 11780 2475 60 0001 C CNN "MFG,MFG#"
|
||||
F 5 " , " V 11780 2475 60 0001 C CNN "VEND1,VEND1#"
|
||||
F 6 "," H 15300 2500 60 0001 C CNN "VEND2,VEND2#"
|
||||
F 7 "C17513" H 13000 1100 50 0001 C CNN "LCSC"
|
||||
1 13000 1100
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,130 @@
|
|||
Ref,Val,Package,PosX,PosY,Rot,Side
|
||||
"C8","0.1uF","C_0805",-7.366000,48.641000,0.000000,top
|
||||
"C9","1uF","C_0805",-7.366000,50.673000,0.000000,top
|
||||
"C10","0.1uF","C_0805",-5.588000,45.339000,270.000000,top
|
||||
"C11","0.1uF","C_0805",-7.366000,53.721000,0.000000,top
|
||||
"C12","4.7uF","C_0805",-26.416000,63.881000,90.000000,top
|
||||
"C13","0.1uF","C_0805",-24.257000,63.897000,90.000000,top
|
||||
"C16","0.22uF","C_0805",-77.597000,90.551000,90.000000,top
|
||||
"C17","0.22uF","C_0805",-54.864000,52.451000,270.000000,top
|
||||
"C23","330pF","C_0805",-30.353000,69.596000,270.000000,top
|
||||
"C24","330pF","C_0805",-23.368000,69.596000,270.000000,top
|
||||
"C25","0.22uF","C_0805",-63.881000,112.395000,270.000000,top
|
||||
"C26","470pF","C_0805",-33.020000,64.770000,270.000000,top
|
||||
"C27","0.22uF","C_0805",-45.212000,103.886000,270.000000,top
|
||||
"C28","330pF","C_0805",-10.541000,63.770000,90.000000,top
|
||||
"C35","1000pF","C_0805",-46.990000,95.631000,90.000000,top
|
||||
"C36","1000pF","C_0805",-34.163000,87.376000,90.000000,top
|
||||
"C37","1000pF","C_0805",-47.561500,118.427500,90.000000,top
|
||||
"C38","1000pF","C_0805",-34.163000,109.601000,90.000000,top
|
||||
"C39","0.33uF","C_0805",-26.543000,50.292000,270.000000,top
|
||||
"C40","0.33uF","C_0805",-29.718000,51.816000,270.000000,top
|
||||
"C41","0.33uF","C_0805",-29.718000,55.626000,270.000000,top
|
||||
"C42","0.33uF","C_0805",-27.051000,56.642000,270.000000,top
|
||||
"C43","4700pF","C_0805",-34.163000,82.423000,270.000000,top
|
||||
"C44","4700pF","C_0805",-29.083000,101.346000,180.000000,top
|
||||
"C45","4700pF","C_0805",-32.893000,101.346000,0.000000,top
|
||||
"C46","4700pF","C_0805",-35.052000,123.190000,180.000000,top
|
||||
"C47","4700pF","C_0805",-20.574000,98.679000,0.000000,top
|
||||
"C48","4700pF","C_0805",-20.447000,80.518000,0.000000,top
|
||||
"C49","4700pF","C_0805",-20.574000,102.870000,0.000000,top
|
||||
"C50","4700pF","C_0805",-20.574000,121.285000,0.000000,top
|
||||
"C55","1000pF","C_0805",-5.461000,94.742000,270.000000,top
|
||||
"C56","1000pF","C_0805",-5.334000,84.836000,270.000000,top
|
||||
"C57","1000pF","C_0805",-4.826000,107.680000,270.000000,top
|
||||
"C58","1000pF","C_0805",-5.080000,118.491000,270.000000,top
|
||||
"C59","330pF","C_0805",-1.651000,59.436000,90.000000,top
|
||||
"C60","330pF","C_0805",-3.683000,59.436000,90.000000,top
|
||||
"C63","1000pF","C_0805",-34.163000,129.921000,90.000000,top
|
||||
"C64","0.33uF","C_0805",-26.543000,60.274200,90.000000,top
|
||||
"C65","4700pF","C_0805",-35.052000,125.222000,180.000000,top
|
||||
"C67","4700pF","C_0805",-20.574000,123.317000,0.000000,top
|
||||
"C71","1000pF","C_0805",-4.445000,129.540000,270.000000,top
|
||||
"C73","330pF","C_0805",-5.715000,59.436000,90.000000,top
|
||||
"D1","LED_Small","LED_0805_2012Metric",-8.255000,28.575000,90.000000,top
|
||||
"D2","LED_Small","LED_0805_2012Metric",-10.795000,28.575000,90.000000,top
|
||||
"D3","LED_Small","LED_0805_2012Metric",-13.335000,28.575000,90.000000,top
|
||||
"D4","LED_Small","LED_0805_2012Metric",-15.875000,28.575000,90.000000,top
|
||||
"D5","LED_Small","LED_0805_2012Metric",-18.415000,28.575000,90.000000,top
|
||||
"D6","LED_Small","LED_0805_2012Metric",-20.955000,28.575000,90.000000,top
|
||||
"D7","LED_Small","LED_0805_2012Metric",-23.495000,28.575000,90.000000,top
|
||||
"D8","LED_Small","LED_0805_2012Metric",-26.035000,28.575000,90.000000,top
|
||||
"D9","FFD10UP20S","TO-252-2Lead",-45.593000,72.136000,270.000000,top
|
||||
"D10","SBR10200CTL","TO-252-2Lead",-36.068000,95.631000,90.000000,top
|
||||
"D11","SBR10200CTL","TO-252-2Lead",-36.068000,118.491000,90.000000,top
|
||||
"D12","STPS2H100UY","D_SMB",-20.193000,93.726000,90.000000,top
|
||||
"D13","STPS2H100UY","D_SMB",-20.193000,85.471000,270.000000,top
|
||||
"D14","STPS2H100UY","D_SMB",-20.193000,107.696000,270.000000,top
|
||||
"D15","STPS2H100UY","D_SMB",-20.193000,116.586000,90.000000,top
|
||||
"D16","STPS2H100UY","D_SMB",-28.448000,133.731000,0.000000,top
|
||||
"D17","STPS2H100UY","D_SMB",-20.193000,128.016000,270.000000,top
|
||||
"D18","LED_Small","LED_0805_2012Metric",-5.715000,28.575000,90.000000,top
|
||||
"D19","LED_Small","LED_0805_2012Metric",-51.435000,28.575000,90.000000,top
|
||||
"D20","LED_Small","LED_0805_2012Metric",-46.355000,28.575000,90.000000,top
|
||||
"D21","LED_Small","LED_0805_2012Metric",-41.275000,28.575000,90.000000,top
|
||||
"D22","LED_Small","LED_0805_2012Metric",-36.195000,28.575000,90.000000,top
|
||||
"D23","LED_Small","LED_0805_2012Metric",-33.655000,28.575000,90.000000,top
|
||||
"D24","LED_Small","LED_0805_2012Metric",-31.115000,28.575000,90.000000,top
|
||||
"D25","LED_Small","LED_0805_2012Metric",-48.895000,28.575000,90.000000,top
|
||||
"D26","LED_Small","LED_0805_2012Metric",-43.815000,28.575000,90.000000,top
|
||||
"D27","LED_Small","LED_0805_2012Metric",-38.735000,28.575000,90.000000,top
|
||||
"D28","LED_Small","LED_0805_2012Metric",-56.515000,133.985000,0.000000,top
|
||||
"D29","LED_Small","LED_0805_2012Metric",-28.575000,28.575000,90.000000,top
|
||||
"D30","Zener_62V","D_MiniMELF",-72.390000,119.380000,90.000000,top
|
||||
"D31","LED_Small","LED_0805_2012Metric",-72.390000,128.270000,270.000000,top
|
||||
"D32","LED_Small","LED_0805_2012Metric",-51.435000,49.530000,0.000000,top
|
||||
"D33","LED_Small","LED_0805_2012Metric",-51.435000,46.355000,0.000000,top
|
||||
"L2","10uH","IHLP6767GZER100M01",-84.455000,38.735000,270.000000,top
|
||||
"Q2","BUK9230-100B","TO-252-2Lead",-36.703000,64.516000,90.000000,top
|
||||
"Q3","BUK9230-100B","TO-252-2Lead",-49.403000,95.631000,90.000000,top
|
||||
"Q4","BUK9230-100B","TO-252-2Lead",-36.957000,87.376000,90.000000,top
|
||||
"Q5","BUK9230-100B","TO-252-2Lead",-50.355500,118.427500,90.000000,top
|
||||
"Q6","BUK9230-100B","TO-252-2Lead",-36.830000,109.601000,90.000000,top
|
||||
"Q7","BUK9230-100B","TO-252-2Lead",-8.128000,95.631000,90.000000,top
|
||||
"Q8","BUK9230-100B","TO-252-2Lead",-8.128000,86.741000,90.000000,top
|
||||
"Q9","BUK9230-100B","TO-252-2Lead",-8.128000,109.601000,90.000000,top
|
||||
"Q10","BUK9230-100B","TO-252-2Lead",-8.128000,118.491000,90.000000,top
|
||||
"Q11","BUK9230-100B","TO-252-2Lead",-37.084000,129.921000,90.000000,top
|
||||
"Q12","BUK9230-100B","TO-252-2Lead",-7.620000,129.921000,90.000000,top
|
||||
"R1","1k","R_0805",-8.255000,32.385000,90.000000,top
|
||||
"R2","1k","R_0805",-10.795000,32.385000,90.000000,top
|
||||
"R3","1k","R_0805",-13.335000,32.385000,90.000000,top
|
||||
"R4","1k","R_0805",-15.875000,32.385000,90.000000,top
|
||||
"R5","1k","R_0805",-18.415000,32.385000,90.000000,top
|
||||
"R6","1k","R_0805",-20.955000,32.385000,90.000000,top
|
||||
"R7","1k","R_0805",-23.495000,32.385000,90.000000,top
|
||||
"R8","1k","R_0805",-26.035000,32.385000,90.000000,top
|
||||
"R9","5.1R","R_0805",-30.353000,73.406000,270.000000,top
|
||||
"R10","5.1R","R_0805",-23.368000,73.406000,270.000000,top
|
||||
"R11","10R","R_0805",-32.893000,61.849000,0.000000,top
|
||||
"R12","0R010","R_1206_HandSoldering",-14.478000,72.136000,90.000000,top
|
||||
"R13","10R","R_0805",-47.498000,90.551000,270.000000,top
|
||||
"R14","10R","R_0805",-36.703000,81.026000,270.000000,top
|
||||
"R15","10R","R_0805",-47.561500,114.173000,270.000000,top
|
||||
"R16","10R","R_0805",-36.703000,103.886000,270.000000,top
|
||||
"R17","10R","R_0805",-10.414000,79.121000,270.000000,top
|
||||
"R18","10R","R_0805",-10.414000,82.296000,180.000000,top
|
||||
"R19","10R","R_0805",-10.033000,104.648000,180.000000,top
|
||||
"R20","10R","R_0805",-10.033000,101.727000,270.000000,top
|
||||
"R21","0R015","R_1206_HandSoldering",-2.032000,90.043000,270.000000,top
|
||||
"R22","0R015","R_1206_HandSoldering",-2.159000,112.014000,270.000000,top
|
||||
"R23","10R","R_0805",-38.036500,124.904500,270.000000,top
|
||||
"R24","10R","R_0805",-9.398000,124.206000,270.000000,top
|
||||
"R25","1k","R_0805",-5.715000,32.385000,90.000000,top
|
||||
"R26","0R015","R_1206_HandSoldering",-1.905000,129.921000,270.000000,top
|
||||
"R27","1k","R_0805",-51.435000,32.385000,90.000000,top
|
||||
"R28","1k","R_0805",-46.355000,32.385000,90.000000,top
|
||||
"R29","1k","R_0805",-41.275000,32.385000,90.000000,top
|
||||
"R30","1k","R_0805",-36.195000,32.385000,90.000000,top
|
||||
"R31","1k","R_0805",-33.655000,32.385000,90.000000,top
|
||||
"R32","1k","R_0805",-31.115000,32.385000,90.000000,top
|
||||
"R33","1k","R_0805",-48.895000,32.385000,90.000000,top
|
||||
"R34","1k","R_0805",-43.815000,32.385000,90.000000,top
|
||||
"R35","1k","R_0805",-38.735000,32.385000,90.000000,top
|
||||
"R36","1k","R_0805",-52.705000,133.985000,0.000000,top
|
||||
"R37","1k","R_0805",-28.575000,32.385000,90.000000,top
|
||||
"R38","1k","R_0805",-72.390000,124.460000,270.000000,top
|
||||
"R39","1k","R_0805",-47.625000,49.530000,0.000000,top
|
||||
"R40","1k","R_0805",-47.625000,46.355000,0.000000,top
|
||||
"U4","MC33816","HTQFP-64-1EP_10x10mm_Pitch0.5mm_ThermalPad_for_MC33816",-17.653000,54.356000,90.000000,top
|
||||
"Y1","1MHz","Crystal_SMD_SeikoEpson_MC306-4pin_8.0x3.2mm",-33.020000,45.339000,0.000000,top
|
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
Comment,Designator,Footprint,LCSC, LCSC, MFG,MFG#, VEND1,VEND1#, VEND2,VEND2#
|
||||
"0.1uF","C10,C11,C13,C8","rusefi_lib:C_0805","","C49678","AVX,08055C104MAT2A","DIGI,478-3351-1-ND","JLCPCB,C49678"
|
||||
"4.7uF","C12","rusefi_lib:C_0805","","C1779","Taiyo Yuden,TMK212AB7475KG-T","DIGI,587-2990-1-ND","JLCPCB,C1779"
|
||||
"1000uF","C14,C15","Capacitors_ThroughHole:CP_Radial_D22.0mm_P10.00mm_SnapIn","","","Cornell,SLPX102M100A3P3","DIGI,338-1553-ND",","
|
||||
"390uF","C21,C22","Capacitors_ThroughHole:CP_Radial_D16.0mm_P7.50mm","","","Nichicon,UHE2A391MHD","DIGI,493-1680-ND",","
|
||||
"0.22uF","C25,C27,C17,C16","rusefi_lib:C_0805","","","KEMET,C0805C224M1RACTU","DIGI,399-9205-1-ND",","
|
||||
"470pF","C26","rusefi_lib:C_0805","","C1743","TDK,CGA4C2C0G2A471J060AA","DIGI,445-6953-1-ND","JLCPCB,C1743"
|
||||
"1000pF","C38,C37,C57,C58,C63,C71,C36,C35,C56,C55","rusefi_lib:C_0805","","C209838","avx,08051C102KAT2A","DIGI,478-1352-1-ND","JLCPCB,C209838"
|
||||
"0.33uF","C41,C64,C39,C40,C42","rusefi_lib:C_0805","","C1740","Yageo,CC0805KKX7R8BB334","DIGI,311-3385-1-ND","JLCPCB,C1740"
|
||||
"4700pF","C45,C49,C46,C50,C65,C67,C44,C48,C43,C47","rusefi_lib:C_0805","","C21217","TDK,C2012C0G2A472J125AA","DIGI,445-2324-1-ND","JLCPCB,C21217"
|
||||
"330pF","C60,C23,C24,C28,C73,C59","rusefi_lib:C_0805","","C51207","Kemet,C0805C331J1GACTU","DIGI,399-1131-1-ND","JLCPCB,C51207"
|
||||
"1uF","C9","rusefi_lib:C_0805","","C28323","Yageo,CC0805KKX7R8BB105","DIGI,311-1456-1-ND","JLCPCB,C28323"
|
||||
"SBR10200CTL","D11,D10","TO_SOT_Packages_SMD:TO-252-2Lead","","C135494","Diodes,SBR10200CTL-13","DIGI,SBR10200CTL-13DICT-ND",","
|
||||
"STPS2H100UY","D17,D14,D15,D16,D13,D12","Diodes_SMD:D_SMB","","C157420","ST,STPS2H100UY","DIGI,497-11093-1-ND",","
|
||||
"LED_Small","D26,D25,D27,D29,D2,D1,D4,D3,D5,D6,D7,D8,D19,D18,D20,D21,D22,D23,D24,D31,D32,D28,D33","LED_SMD:LED_0805_2012Metric","","C2296","","",""
|
||||
"Zener_62V","D30","Diode_SMD:D_MiniMELF","","C8088","","",""
|
||||
"FFD10UP20S","D9","TO_SOT_Packages_SMD:TO-252-2Lead","","","ONSEMI,FFD10UP20S","DIGI,FFD10UP20SCT-ND",","
|
||||
"INJ_Term","J10,J11,J9","TerminalBlock:TerminalBlock_bornier-2_P5.08mm","","","onshore,OSTTG025100B","DIGI,ED2703-ND",","
|
||||
"CONN_01X01","J15","Connector_Pin:Pin_D1.4mm_L8.5mm_W2.8mm_FlatFork",""
|
||||
"Conn_01x02","J20","TerminalBlock:TerminalBlock_bornier-2_P5.08mm","","","TE,282834-2","DIGI,A98333-ND",""
|
||||
"CONN_02X08","J3,J4","Pin_Headers:Pin_Header_Straight_2x08_Pitch2.54mm","","","sullins,SBH11-PBPC-D08-ST-BK","DIGI,S9171-ND",","
|
||||
"CONN_01X03","J7,J5,J6,J14","Pin_Headers:Pin_Header_Straight_1x03_Pitch2.54mm",""
|
||||
"INJ_Term","J8,J12","Terminal_Blocks:TerminalBlock_bornier-2_P5.08mm","","","onshore,OSTTG025100B","DIGI,ED2703-ND",","
|
||||
"6uH","L1","rusefi_lib:744710610-Inductor","","","Würth Elektronik,744710610","DIGI,732-3255-ND",","
|
||||
"10uH","L2","rusefi_lib:IHLP6767GZER100M01","","","Vishay,IHLP6767GZER100M01","DIGI,541-1259-1-ND",","
|
||||
"BUK9230-100B","Q6,Q5,Q9,Q10,Q11,Q2,Q12,Q4,Q3,Q8,Q7","TO_SOT_Packages_SMD:TO-252-2Lead","","C194346","Nexperia,BUK9230-100B","DIGI,1727-4708-1-ND",","
|
||||
"0R010","R12","Resistors_SMD:R_1206_HandSoldering","","","Ohmite,MCS1632R010FER","DIGI,MCS1632R010FERCT-ND",","
|
||||
"10R","R16,R15,R19,R20,R11,R23,R24,R14,R13,R18,R17","rusefi_lib:R_0805","","C17403","Stackpole,RMCF0805JG10R0","DIGI,RMCF0805JG10R0CT-ND","JLCPCB,C17403"
|
||||
"0R015","R22,R26,R21","Resistors_SMD:R_1206_HandSoldering","","C201281","Panasonic,ERJ-8CWFR015V","DIGI,P0.015BVCT-ND","JLCPCB,C201281"
|
||||
"1k","R34,R33,R35,R37,R2,R1,R4,R3,R5,R6,R7,R8,R27,R25,R28,R29,R30,R31,R32,R38,R39,R36,R40","rusefi_lib:R_0805","","C17513"," , "," , ",","
|
||||
"5.1R","R9,R10","rusefi_lib:R_0805","","C247080","Stackpole,RMCF0805JT5R10","DIGI,RMCF0805JT5R10CT-ND","JLCPCB,C247080"
|
||||
"CONN_01X01","TP23,TP24,TP103,TP104,TP101,TP102,TP105,TP106,TP4,TP7,TP3,TP6,TP5,TP2,TP8","Connector_Pin:Pin_D0.7mm_L6.5mm_W1.8mm_FlatFork",""
|
||||
"MC33816","U4","rusefi_lib:HTQFP-64-1EP_10x10mm_Pitch0.5mm_ThermalPad_for_MC33816","","","FreeScale,MC33816AE","Mouser,841-MC33816AE",","
|
||||
"1MHz","Y1","Crystals:Crystal_SMD_SeikoEpson_MC306-4pin_8.0x3.2mm","","","epson,SG7050CAN 1.000000M-TJGA3","DIGI,SER3990CT-ND",""
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
@ -0,0 +1,130 @@
|
|||
Designator,Val,Mid X,Mid Y,Rotation,Layer
|
||||
C8,0.1uF,-7.366000,48.641000,0.000000,top
|
||||
C9,1uF,-7.366000,50.673000,0.000000,top
|
||||
C10,0.1uF,-5.588000,45.339000,270.000000,top
|
||||
C11,0.1uF,-7.366000,53.721000,0.000000,top
|
||||
C12,4.7uF,-26.416000,63.881000,90.000000,top
|
||||
C13,0.1uF,-24.257000,63.897000,90.000000,top
|
||||
C16,0.22uF,-77.597000,90.551000,90.000000,top
|
||||
C17,0.22uF,-54.864000,52.451000,270.000000,top
|
||||
C23,330pF,-30.353000,69.596000,270.000000,top
|
||||
C24,330pF,-23.368000,69.596000,270.000000,top
|
||||
C25,0.22uF,-63.881000,112.395000,270.000000,top
|
||||
C26,470pF,-33.020000,64.770000,270.000000,top
|
||||
C27,0.22uF,-45.212000,103.886000,270.000000,top
|
||||
C28,330pF,-10.541000,63.770000,90.000000,top
|
||||
C35,1000pF,-46.990000,95.631000,90.000000,top
|
||||
C36,1000pF,-34.163000,87.376000,90.000000,top
|
||||
C37,1000pF,-47.561500,118.427500,90.000000,top
|
||||
C38,1000pF,-34.163000,109.601000,90.000000,top
|
||||
C39,0.33uF,-26.543000,50.292000,270.000000,top
|
||||
C40,0.33uF,-29.718000,51.816000,270.000000,top
|
||||
C41,0.33uF,-29.718000,55.626000,270.000000,top
|
||||
C42,0.33uF,-27.051000,56.642000,270.000000,top
|
||||
C43,4700pF,-34.163000,82.423000,270.000000,top
|
||||
C44,4700pF,-29.083000,101.346000,180.000000,top
|
||||
C45,4700pF,-32.893000,101.346000,0.000000,top
|
||||
C46,4700pF,-35.052000,123.190000,180.000000,top
|
||||
C47,4700pF,-20.574000,98.679000,0.000000,top
|
||||
C48,4700pF,-20.447000,80.518000,0.000000,top
|
||||
C49,4700pF,-20.574000,102.870000,0.000000,top
|
||||
C50,4700pF,-20.574000,121.285000,0.000000,top
|
||||
C55,1000pF,-5.461000,94.742000,270.000000,top
|
||||
C56,1000pF,-5.334000,84.836000,270.000000,top
|
||||
C57,1000pF,-4.826000,107.680000,270.000000,top
|
||||
C58,1000pF,-5.080000,118.491000,270.000000,top
|
||||
C59,330pF,-1.651000,59.436000,90.000000,top
|
||||
C60,330pF,-3.683000,59.436000,90.000000,top
|
||||
C63,1000pF,-34.163000,129.921000,90.000000,top
|
||||
C64,0.33uF,-26.543000,60.274200,90.000000,top
|
||||
C65,4700pF,-35.052000,125.222000,180.000000,top
|
||||
C67,4700pF,-20.574000,123.317000,0.000000,top
|
||||
C71,1000pF,-4.445000,129.540000,270.000000,top
|
||||
C73,330pF,-5.715000,59.436000,90.000000,top
|
||||
D1,LED_Small,-8.255000,28.575000,90.000000,top
|
||||
D2,LED_Small,-10.795000,28.575000,90.000000,top
|
||||
D3,LED_Small,-13.335000,28.575000,90.000000,top
|
||||
D4,LED_Small,-15.875000,28.575000,90.000000,top
|
||||
D5,LED_Small,-18.415000,28.575000,90.000000,top
|
||||
D6,LED_Small,-20.955000,28.575000,90.000000,top
|
||||
D7,LED_Small,-23.495000,28.575000,90.000000,top
|
||||
D8,LED_Small,-26.035000,28.575000,90.000000,top
|
||||
D9,FFD10UP20S,-45.593000,72.136000,0,top
|
||||
D10,SBR10200CTL,-36.068000,95.631000,180,top
|
||||
D11,SBR10200CTL,-36.068000,118.491000,180,top
|
||||
D12,STPS2H100UY,-20.193000,93.726000,90.000000,top
|
||||
D13,STPS2H100UY,-20.193000,85.471000,270.000000,top
|
||||
D14,STPS2H100UY,-20.193000,107.696000,270.000000,top
|
||||
D15,STPS2H100UY,-20.193000,116.586000,90.000000,top
|
||||
D16,STPS2H100UY,-28.448000,133.731000,0.000000,top
|
||||
D17,STPS2H100UY,-20.193000,128.016000,270.000000,top
|
||||
D18,LED_Small,-5.715000,28.575000,90.000000,top
|
||||
D19,LED_Small,-51.435000,28.575000,90.000000,top
|
||||
D20,LED_Small,-46.355000,28.575000,90.000000,top
|
||||
D21,LED_Small,-41.275000,28.575000,90.000000,top
|
||||
D22,LED_Small,-36.195000,28.575000,90.000000,top
|
||||
D23,LED_Small,-33.655000,28.575000,90.000000,top
|
||||
D24,LED_Small,-31.115000,28.575000,90.000000,top
|
||||
D25,LED_Small,-48.895000,28.575000,90.000000,top
|
||||
D26,LED_Small,-43.815000,28.575000,90.000000,top
|
||||
D27,LED_Small,-38.735000,28.575000,90.000000,top
|
||||
D28,LED_Small,-56.515000,133.985000,0.000000,top
|
||||
D29,LED_Small,-28.575000,28.575000,90.000000,top
|
||||
D30,Zener_62V,-72.390000,119.380000,90.000000,top
|
||||
D31,LED_Small,-72.390000,128.270000,270.000000,top
|
||||
D32,LED_Small,-51.435000,49.530000,0.000000,top
|
||||
D33,LED_Small,-51.435000,46.355000,0.000000,top
|
||||
L2,10uH,-84.455000,38.735000,270.000000,top
|
||||
Q2,BUK9230-100B,-36.703000,64.516000,180,top
|
||||
Q3,BUK9230-100B,-49.403000,95.631000,180,top
|
||||
Q4,BUK9230-100B,-36.957000,87.376000,180,top
|
||||
Q5,BUK9230-100B,-50.355500,118.427500,180,top
|
||||
Q6,BUK9230-100B,-36.830000,109.601000,180,top
|
||||
Q7,BUK9230-100B,-8.128000,95.631000,180,top
|
||||
Q8,BUK9230-100B,-8.128000,86.741000,180,top
|
||||
Q9,BUK9230-100B,-8.128000,109.601000,180,top
|
||||
Q10,BUK9230-100B,-8.128000,118.491000,180,top
|
||||
Q11,BUK9230-100B,-37.084000,129.921000,180,top
|
||||
Q12,BUK9230-100B,-7.620000,129.921000,180,top
|
||||
R1,1k,-8.255000,32.385000,90.000000,top
|
||||
R2,1k,-10.795000,32.385000,90.000000,top
|
||||
R3,1k,-13.335000,32.385000,90.000000,top
|
||||
R4,1k,-15.875000,32.385000,90.000000,top
|
||||
R5,1k,-18.415000,32.385000,90.000000,top
|
||||
R6,1k,-20.955000,32.385000,90.000000,top
|
||||
R7,1k,-23.495000,32.385000,90.000000,top
|
||||
R8,1k,-26.035000,32.385000,90.000000,top
|
||||
R9,5.1R,-30.353000,73.406000,270.000000,top
|
||||
R10,5.1R,-23.368000,73.406000,270.000000,top
|
||||
R11,10R,-32.893000,61.849000,0.000000,top
|
||||
R12,0R010,-14.478000,72.136000,90.000000,top
|
||||
R13,10R,-47.498000,90.551000,270.000000,top
|
||||
R14,10R,-36.703000,81.026000,270.000000,top
|
||||
R15,10R,-47.561500,114.173000,270.000000,top
|
||||
R16,10R,-36.703000,103.886000,270.000000,top
|
||||
R17,10R,-10.414000,79.121000,270.000000,top
|
||||
R18,10R,-10.414000,82.296000,180.000000,top
|
||||
R19,10R,-10.033000,104.648000,180.000000,top
|
||||
R20,10R,-10.033000,101.727000,270.000000,top
|
||||
R21,0R015,-2.032000,90.043000,270.000000,top
|
||||
R22,0R015,-2.159000,112.014000,270.000000,top
|
||||
R23,10R,-38.036500,124.904500,270.000000,top
|
||||
R24,10R,-9.398000,124.206000,270.000000,top
|
||||
R25,1k,-5.715000,32.385000,90.000000,top
|
||||
R26,0R015,-1.905000,129.921000,270.000000,top
|
||||
R27,1k,-51.435000,32.385000,90.000000,top
|
||||
R28,1k,-46.355000,32.385000,90.000000,top
|
||||
R29,1k,-41.275000,32.385000,90.000000,top
|
||||
R30,1k,-36.195000,32.385000,90.000000,top
|
||||
R31,1k,-33.655000,32.385000,90.000000,top
|
||||
R32,1k,-31.115000,32.385000,90.000000,top
|
||||
R33,1k,-48.895000,32.385000,90.000000,top
|
||||
R34,1k,-43.815000,32.385000,90.000000,top
|
||||
R35,1k,-38.735000,32.385000,90.000000,top
|
||||
R36,1k,-52.705000,133.985000,0.000000,top
|
||||
R37,1k,-28.575000,32.385000,90.000000,top
|
||||
R38,1k,-72.390000,124.460000,270.000000,top
|
||||
R39,1k,-47.625000,49.530000,0.000000,top
|
||||
R40,1k,-47.625000,46.355000,0.000000,top
|
||||
U4,MC33816,-17.653000,54.356000,90.000000,top
|
||||
Y1,1MHz,-33.020000,45.339000,0.000000,top
|
|
|
@ -0,0 +1,2 @@
|
|||
python jlc_kicad_tools/KC-POS_to_JLC.py Common_Rail_MC33816_R0.3.2
|
||||
pause
|
|
@ -0,0 +1,173 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2019 Matthew Lai
|
||||
#
|
||||
# This file is part of JLC Kicad Tools.
|
||||
#
|
||||
# JLC Kicad Tools is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# JLC Kicad Tools is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with JLC Kicad Tools. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import errno
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
import getpass
|
||||
|
||||
root = tk.Tk()
|
||||
root.withdraw()
|
||||
|
||||
user = getpass.getuser()
|
||||
file_name = filedialog.askopenfilename(initialdir=os.getcwd(), initialfile='68_vag_PNP_R0.1-top-pos.csv',title = "choose your file",filetypes = (("all files","*.*"),("CSV","*.csv")))
|
||||
|
||||
|
||||
print ('filename = ' + file_name)
|
||||
|
||||
# JLC requires columns to be named a certain way.
|
||||
HEADER_REPLACEMENT_TABLE={
|
||||
"Ref": "Designator",
|
||||
"Val": "Val",
|
||||
"Package": "PackageReference",
|
||||
"PosX": "Mid X",
|
||||
"PosY": "Mid Y",
|
||||
"Rot": "Rotation",
|
||||
"Side": "Layer",
|
||||
}
|
||||
|
||||
ROW_REPLACEMENT_TABLE={
|
||||
"TopLayer": "Top",
|
||||
"BottomLayer": "Bottom",
|
||||
}
|
||||
|
||||
def ReadDB(filename):
|
||||
db = {}
|
||||
with open(filename) as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',')
|
||||
for row in reader:
|
||||
if row[0] == "Footprint pattern":
|
||||
continue
|
||||
else:
|
||||
db[re.compile(row[0])] = int(row[1])
|
||||
logging.info("Read {} rules from {}".format(len(db), filename))
|
||||
return db
|
||||
|
||||
def FixRotations(input_filename, output_filename, db):
|
||||
with open(input_filename) as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',')
|
||||
writer = csv.writer(open(output_filename, 'w', newline=''), delimiter=',')
|
||||
package_index = None
|
||||
rotation_index = None
|
||||
for row in reader:
|
||||
if not package_index:
|
||||
# This is the first row. Find "Package" and "Rot" column indices.
|
||||
for i in range(len(row)):
|
||||
if row[i] == "Package":
|
||||
package_index = i
|
||||
elif row[i] == "Rot":
|
||||
rotation_index = i
|
||||
if package_index is None:
|
||||
logging.warning("Failed to find 'Package' column in the csv file")
|
||||
return False
|
||||
if rotation_index is None:
|
||||
logging.warning("Failed to find 'Rot' column in the csv file")
|
||||
return False
|
||||
# Replace column names with labels JLC wants.
|
||||
for i in range(len(row)):
|
||||
if row[i] in HEADER_REPLACEMENT_TABLE:
|
||||
row[i] = HEADER_REPLACEMENT_TABLE[row[i]]
|
||||
else:
|
||||
for pattern, correction in db.items():
|
||||
if pattern.match(row[package_index]):
|
||||
logging.info("Footprint {} matched {}. Applying {} deg correction"
|
||||
.format(row[package_index], pattern.pattern, correction))
|
||||
row[rotation_index] = "{0:.0f}".format((float(row[rotation_index]) + correction) % 360)
|
||||
break
|
||||
for i in range(len(row)):
|
||||
if row[i] in ROW_REPLACEMENT_TABLE:
|
||||
row[i] = ROW_REPLACEMENT_TABLE[row[i]]
|
||||
del row[package_index]
|
||||
writer.writerow(row)
|
||||
return True
|
||||
|
||||
DEFAULT_DB_PATH="cpl_KC-to-JLC-rotations_db.csv"
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description='Generates BOM and CPL in CSV fashion to be used in JLCPCB Assembly Service', prog='generate_jlc_files')
|
||||
parser.add_argument('project_dir', metavar='INPUT_DIRECTORY', type=os.path.abspath, help='Directory of KiCad project. Name should match KiCad project name.')
|
||||
parser.add_argument('-d', '--database', metavar='DATABASE', type=str, help='Filename of database', default=os.path.join(os.path.dirname(__file__), DEFAULT_DB_PATH))
|
||||
verbosity = parser.add_argument_group('verbosity arguments')
|
||||
verbosity.add_argument('-v', '--verbose', help='Increases log verbosity for each occurrence', dest='verbose_count', action="count", default=0)
|
||||
verbosity.add_argument('--warn-no-lcsc-partnumber', help='Enable warning output if lcsc part number is not found', dest='warn_no_partnumber', action='store_true')
|
||||
parser.add_argument('--assume-same-lcsc-partnumber', help='Assume same lcsc partnumber for all components of a group', action='store_true', dest='assume_same_lcsc_partnumber')
|
||||
parser.add_argument('-o', '--output', metavar='OUTPUT_DIRECTORY', dest='output_dir', type=os.path.abspath, help='Output directory. Default: INPUT_DIRECTORY')
|
||||
|
||||
#if (len(sys.argv) == 1):
|
||||
# parser.print_help()
|
||||
# sys.exit()
|
||||
print ("debug120")
|
||||
# Parse arguments
|
||||
opts = parser.parse_args(sys.argv[1:])
|
||||
|
||||
# Default log level is WARNING
|
||||
logging.basicConfig(format="%(message)s", level=max(logging.WARNING - opts.verbose_count * 10, logging.NOTSET))
|
||||
|
||||
if not os.path.isdir(opts.project_dir):
|
||||
logging.error("Failed to open project directory: {}".format(opts.project_dir))
|
||||
return errno.ENOENT
|
||||
print ("debug130")
|
||||
# Set default output directory
|
||||
if opts.output_dir == None:
|
||||
opts.output_dir = opts.project_dir
|
||||
|
||||
if not os.path.isdir(opts.output_dir):
|
||||
logging.info("Creating output directory {}".format(opts.output_dir))
|
||||
os.mkdir(opts.output_dir)
|
||||
print ("debug138")
|
||||
project_name = os.path.basename(opts.project_dir)
|
||||
logging.debug("Project name is '%s'.", project_name)
|
||||
#cpl_filename = project_name + "-top-pos.csv"
|
||||
print ("debug 142 " + project_name + "-top-pos.csv")
|
||||
cpl_filename = file_name
|
||||
cpl_path = None
|
||||
|
||||
for dir_name, subdir_list, file_list in os.walk(opts.project_dir):
|
||||
for file_name in file_list:
|
||||
if file_name == cpl_filename:
|
||||
cpl_path = os.path.join(dir_name, file_name)
|
||||
cpl_path = file_name
|
||||
|
||||
if cpl_path is None:
|
||||
logging.error((
|
||||
"Failed to find CPL file: {} in {} (and sub-directories). "
|
||||
"Run 'File -> Fabrication Outputs -> Footprint Position (.pos) File' in Pcbnew. "
|
||||
"Settings: 'CSV', 'mm', 'single file for board'.").format(cpl_filename, opts.project_dir))
|
||||
return errno.ENOENT
|
||||
|
||||
logging.info("CPL file found at: {}".format(cpl_path))
|
||||
|
||||
cpl_output_path = os.path.join(opts.output_dir, project_name + "_JLC_CPL.csv")
|
||||
|
||||
db = ReadDB(opts.database)
|
||||
if FixRotations(cpl_path, cpl_output_path, db):
|
||||
logging.info("JLC CPL file written to: {}".format(cpl_output_path))
|
||||
else:
|
||||
return errno.EINVAL
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2019 Matthew Lai
|
||||
#
|
||||
# This file is part of JLC Kicad Tools.
|
||||
#
|
||||
# JLC Kicad Tools is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# JLC Kicad Tools is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with JLC Kicad Tools. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import errno
|
||||
|
||||
import csv
|
||||
import re
|
||||
import sys
|
||||
import logging
|
||||
|
||||
# JLC requires columns to be named a certain way.
|
||||
HEADER_REPLACEMENT_TABLE={
|
||||
"Ref": "Designator",
|
||||
"Val": "Val",
|
||||
"Package": "PackageReference",
|
||||
"PosX": "Mid X",
|
||||
"PosY": "Mid Y",
|
||||
"Rot": "Rotation",
|
||||
"Side": "Layer",
|
||||
}
|
||||
|
||||
ROW_REPLACEMENT_TABLE={
|
||||
"TopLayer": "Top",
|
||||
"BottomLayer": "Bottom",
|
||||
}
|
||||
|
||||
def ReadDB(filename):
|
||||
db = {}
|
||||
with open(filename) as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',')
|
||||
for row in reader:
|
||||
if row[0] == "Footprint pattern":
|
||||
continue
|
||||
else:
|
||||
db[re.compile(row[0])] = int(row[1])
|
||||
logging.info("Read {} rules from {}".format(len(db), filename))
|
||||
return db
|
||||
|
||||
def FixRotations(input_filename, output_filename, db):
|
||||
with open(input_filename) as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',')
|
||||
writer = csv.writer(open(output_filename, 'w', newline=''), delimiter=',')
|
||||
package_index = None
|
||||
rotation_index = None
|
||||
for row in reader:
|
||||
if not package_index:
|
||||
# This is the first row. Find "Package" and "Rot" column indices.
|
||||
for i in range(len(row)):
|
||||
if row[i] == "Package":
|
||||
package_index = i
|
||||
elif row[i] == "Rot":
|
||||
rotation_index = i
|
||||
if package_index is None:
|
||||
logging.warning("Failed to find 'Package' column in the csv file")
|
||||
return False
|
||||
if rotation_index is None:
|
||||
logging.warning("Failed to find 'Rot' column in the csv file")
|
||||
return False
|
||||
# Replace column names with labels JLC wants.
|
||||
for i in range(len(row)):
|
||||
if row[i] in HEADER_REPLACEMENT_TABLE:
|
||||
row[i] = HEADER_REPLACEMENT_TABLE[row[i]]
|
||||
else:
|
||||
for pattern, correction in db.items():
|
||||
if pattern.match(row[package_index]):
|
||||
logging.info("Footprint {} matched {}. Applying {} deg correction"
|
||||
.format(row[package_index], pattern.pattern, correction))
|
||||
row[rotation_index] = "{0:.0f}".format((float(row[rotation_index]) + correction) % 360)
|
||||
break
|
||||
for i in range(len(row)):
|
||||
if row[i] in ROW_REPLACEMENT_TABLE:
|
||||
row[i] = ROW_REPLACEMENT_TABLE[row[i]]
|
||||
del row[package_index]
|
||||
writer.writerow(row)
|
||||
return True
|
||||
|
||||
DEFAULT_DB_PATH="cpl_KC-to-JLC-rotations_db.csv"
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description='Generates BOM and CPL in CSV fashion to be used in JLCPCB Assembly Service', prog='generate_jlc_files')
|
||||
parser.add_argument('project_dir', metavar='INPUT_DIRECTORY', type=os.path.abspath, help='Directory of KiCad project. Name should match KiCad project name.')
|
||||
parser.add_argument('-d', '--database', metavar='DATABASE', type=str, help='Filename of database', default=os.path.join(os.path.dirname(__file__), DEFAULT_DB_PATH))
|
||||
verbosity = parser.add_argument_group('verbosity arguments')
|
||||
verbosity.add_argument('-v', '--verbose', help='Increases log verbosity for each occurrence', dest='verbose_count', action="count", default=0)
|
||||
verbosity.add_argument('--warn-no-lcsc-partnumber', help='Enable warning output if lcsc part number is not found', dest='warn_no_partnumber', action='store_true')
|
||||
parser.add_argument('--assume-same-lcsc-partnumber', help='Assume same lcsc partnumber for all components of a group', action='store_true', dest='assume_same_lcsc_partnumber')
|
||||
parser.add_argument('-o', '--output', metavar='OUTPUT_DIRECTORY', dest='output_dir', type=os.path.abspath, help='Output directory. Default: INPUT_DIRECTORY')
|
||||
|
||||
if (len(sys.argv) == 1):
|
||||
parser.print_help()
|
||||
sys.exit()
|
||||
|
||||
# Parse arguments
|
||||
opts = parser.parse_args(sys.argv[1:])
|
||||
|
||||
# Default log level is WARNING
|
||||
logging.basicConfig(format="%(message)s", level=max(logging.WARNING - opts.verbose_count * 10, logging.NOTSET))
|
||||
|
||||
if not os.path.isdir(opts.project_dir):
|
||||
logging.error("Failed to open project directory: {}".format(opts.project_dir))
|
||||
return errno.ENOENT
|
||||
|
||||
# Set default output directory
|
||||
if opts.output_dir == None:
|
||||
opts.output_dir = opts.project_dir
|
||||
|
||||
if not os.path.isdir(opts.output_dir):
|
||||
logging.info("Creating output directory {}".format(opts.output_dir))
|
||||
os.mkdir(opts.output_dir)
|
||||
|
||||
project_name = os.path.basename(opts.project_dir)
|
||||
logging.debug("Project name is '%s'.", project_name)
|
||||
cpl_filename = project_name + "-top-pos.csv"
|
||||
cpl_path = None
|
||||
|
||||
for dir_name, subdir_list, file_list in os.walk(opts.project_dir):
|
||||
for file_name in file_list:
|
||||
if file_name == cpl_filename:
|
||||
cpl_path = os.path.join(dir_name, file_name)
|
||||
|
||||
if cpl_path is None:
|
||||
logging.error((
|
||||
"Failed to find CPL file: {} in {} (and sub-directories). "
|
||||
"Run 'File -> Fabrication Outputs -> Footprint Position (.pos) File' in Pcbnew. "
|
||||
"Settings: 'CSV', 'mm', 'single file for board'.").format(cpl_filename, opts.project_dir))
|
||||
return errno.ENOENT
|
||||
|
||||
logging.info("CPL file found at: {}".format(cpl_path))
|
||||
|
||||
cpl_output_path = os.path.join(opts.output_dir, project_name + "_JLC_CPL.csv")
|
||||
|
||||
db = ReadDB(opts.database)
|
||||
if FixRotations(cpl_path, cpl_output_path, db):
|
||||
logging.info("JLC CPL file written to: {}".format(cpl_output_path))
|
||||
else:
|
||||
return errno.EINVAL
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
|
@ -0,0 +1 @@
|
|||
__version__ = '1.0.0'
|
|
@ -0,0 +1,10 @@
|
|||
"Footprint pattern","Correction"
|
||||
"CP_Elec_8x10.5",180
|
||||
"SOT-23",180
|
||||
"D_SMC",180
|
||||
"R_Array_Convex_4x0603",270
|
||||
"SOT-223-3_TabPin2",180
|
||||
"SO-8_5.3x6.2mm_P1.27mm-150+208",90
|
||||
"TSSOP-14_4.4x5mm_P0.65mm",180
|
||||
"SOIC-8_3.9x4.9mm_P1.27mm",90
|
||||
"TO-252-2Lead",90
|
|
|
@ -0,0 +1,76 @@
|
|||
# Copyright (C) 2019 Matthew Lai
|
||||
#
|
||||
# This file is part of JLC Kicad Tools.
|
||||
#
|
||||
# JLC Kicad Tools is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# JLC Kicad Tools is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with JLC Kicad Tools. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import csv
|
||||
import re
|
||||
import sys
|
||||
import logging
|
||||
|
||||
# JLC requires columns to be named a certain way.
|
||||
HEADER_REPLACEMENT_TABLE={
|
||||
"Ref": "Designator",
|
||||
"PosX": "Mid X",
|
||||
"PosY": "Mid Y",
|
||||
"Rot": "Rotation",
|
||||
"Side": "Layer"
|
||||
}
|
||||
|
||||
def ReadDB(filename):
|
||||
db = {}
|
||||
with open(filename) as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',')
|
||||
for row in reader:
|
||||
if row[0] == "Footprint pattern":
|
||||
continue
|
||||
else:
|
||||
db[re.compile(row[0])] = int(row[1])
|
||||
logging.info("Read {} rules from {}".format(len(db), filename))
|
||||
return db
|
||||
|
||||
def FixRotations(input_filename, output_filename, db):
|
||||
with open(input_filename) as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',')
|
||||
writer = csv.writer(open(output_filename, 'w', newline=''), delimiter=',')
|
||||
package_index = None
|
||||
rotation_index = None
|
||||
for row in reader:
|
||||
if not package_index:
|
||||
# This is the first row. Find "Package" and "Rot" column indices.
|
||||
for i in range(len(row)):
|
||||
if row[i] == "Package":
|
||||
package_index = i
|
||||
elif row[i] == "Rot":
|
||||
rotation_index = i
|
||||
if package_index is None:
|
||||
logging.warning("Failed to find 'Package' column in the csv file")
|
||||
return False
|
||||
if rotation_index is None:
|
||||
logging.warning("Failed to find 'Rot' column in the csv file")
|
||||
return False
|
||||
# Replace column names with labels JLC wants.
|
||||
for i in range(len(row)):
|
||||
if row[i] in HEADER_REPLACEMENT_TABLE:
|
||||
row[i] = HEADER_REPLACEMENT_TABLE[row[i]]
|
||||
else:
|
||||
for pattern, correction in db.items():
|
||||
if pattern.match(row[package_index]):
|
||||
logging.info("Footprint {} matched {}. Applying {} deg correction"
|
||||
.format(row[package_index], pattern.pattern, correction))
|
||||
row[rotation_index] = "{0:.6f}".format((float(row[rotation_index]) + correction) % 360)
|
||||
break
|
||||
writer.writerow(row)
|
||||
return True
|
|
@ -0,0 +1,107 @@
|
|||
# Copyright (C) 2019 Matthew Lai
|
||||
# Copyright (C) 1992-2019 Kicad Developers Team
|
||||
#
|
||||
# This file is part of JLC Kicad Tools.
|
||||
#
|
||||
# JLC Kicad Tools is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# JLC Kicad Tools is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with JLC Kicad Tools. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
from jlc_kicad_tools.jlc_lib import kicad_netlist_reader
|
||||
import csv
|
||||
import re
|
||||
import logging
|
||||
|
||||
LCSC_PART_NUMBER_MATCHER=re.compile('^C[0-9]+$')
|
||||
|
||||
def GenerateBOM(input_filename, output_filename, opts):
|
||||
net = kicad_netlist_reader.netlist(input_filename)
|
||||
|
||||
try:
|
||||
f = open(output_filename, mode='w', encoding='utf-8')
|
||||
except IOError:
|
||||
logging.error("Failed to open file for writing: {}".format(output_filename))
|
||||
return False
|
||||
|
||||
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"',
|
||||
quoting=csv.QUOTE_ALL)
|
||||
|
||||
out.writerow(['Comment', 'Designator', 'Footprint', 'LCSC Part #'])
|
||||
|
||||
grouped = net.groupComponents()
|
||||
|
||||
num_groups_found = 0
|
||||
for group in grouped:
|
||||
refs = []
|
||||
lcsc_part_numbers = set()
|
||||
lcsc_part_numbers_none_found = False
|
||||
footprints = set()
|
||||
|
||||
for component in group:
|
||||
refs.append(component.getRef())
|
||||
c = component
|
||||
lcsc_part_number = None
|
||||
|
||||
# Get the field name for the LCSC part number.
|
||||
for field_name in c.getFieldNames():
|
||||
field_value = c.getField(field_name)
|
||||
|
||||
if LCSC_PART_NUMBER_MATCHER.match(field_value):
|
||||
lcsc_part_number = field_value
|
||||
|
||||
if lcsc_part_number:
|
||||
lcsc_part_numbers.add(lcsc_part_number)
|
||||
else:
|
||||
lcsc_part_numbers_none_found = True
|
||||
|
||||
if c.getFootprint() != '':
|
||||
footprints.add(c.getFootprint())
|
||||
|
||||
# Check part numbers for uniqueness
|
||||
if len(lcsc_part_numbers) == 0:
|
||||
if opts.warn_no_partnumber:
|
||||
logging.warning("No LCSC part number found for components {}".format(",".join(refs)))
|
||||
continue
|
||||
elif len(lcsc_part_numbers) != 1:
|
||||
logging.error("Components {components} from same group have different LCSC part numbers: {partnumbers}".format(
|
||||
components = ", ".join(refs),
|
||||
partnumbers = ", ".join(lcsc_part_numbers)))
|
||||
return False
|
||||
lcsc_part_number = list(lcsc_part_numbers)[0]
|
||||
|
||||
if (not opts.assume_same_lcsc_partnumber) and (lcsc_part_numbers_none_found):
|
||||
logging.error("Components {components} from same group do not all have LCSC part number {partnumber} set. Use --assume-same-lcsc-partnumber to ignore.".format(
|
||||
components = ", ".join(refs),
|
||||
partnumber = lcsc_part_number))
|
||||
return False
|
||||
|
||||
# Check footprints for uniqueness
|
||||
if (len(footprints) == 0):
|
||||
logging.error("No footprint found for components {}".format(",".join(refs)))
|
||||
return False
|
||||
if len(footprints) != 1:
|
||||
logging.error("Components {components} from same group have different foot prints: {footprints}".format(
|
||||
components = ", ".join(refs),
|
||||
footprints = ", ".join(footprints)))
|
||||
return False
|
||||
footprint = list(footprints)[0]
|
||||
|
||||
# They don't seem to like ':' in footprint names.
|
||||
footprint = footprint[(footprint.find(':') + 1):]
|
||||
|
||||
# Fill in the component groups common data
|
||||
out.writerow([c.getValue(), ",".join(refs), footprint, lcsc_part_number])
|
||||
num_groups_found += 1
|
||||
|
||||
logging.info("{} component groups found from BOM file.".format(num_groups_found))
|
||||
|
||||
return True
|
|
@ -0,0 +1,794 @@
|
|||
# Copyright (C) 1992-2019 Kicad Developers Team
|
||||
#
|
||||
# This file is part of JLC Kicad Tools.
|
||||
#
|
||||
# JLC Kicad Tools is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# JLC Kicad Tools is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with JLC Kicad Tools. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#
|
||||
# KiCad python module for interpreting generic netlists which can be used
|
||||
# to generate Bills of materials, etc.
|
||||
#
|
||||
# Remember these files use UTF8 encoding
|
||||
#
|
||||
# No string formatting is used on purpose as the only string formatting that
|
||||
# is current compatible with python 2.4+ to 3.0+ is the '%' method, and that
|
||||
# is due to be deprecated in 3.0+ soon
|
||||
#
|
||||
|
||||
"""
|
||||
@package
|
||||
Helper module for interpreting generic netlist and build custom
|
||||
bom generators or netlists in foreign format
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import xml.sax as sax
|
||||
import re
|
||||
import pdb
|
||||
import logging
|
||||
|
||||
#-----<Configure>----------------------------------------------------------------
|
||||
|
||||
# excluded_fields is a list of regular expressions. If any one matches a field
|
||||
# from either a component or a libpart, then that will not be included as a
|
||||
# column in the BOM. Otherwise all columns from all used libparts and components
|
||||
# will be unionized and will appear. Some fields are impossible to blacklist, such
|
||||
# as Ref, Value, Footprint, and Datasheet. Additionally Qty and Item are supplied
|
||||
# unconditionally as columns, and may not be removed.
|
||||
excluded_fields = [
|
||||
#'Price@1000'
|
||||
]
|
||||
|
||||
|
||||
# You may exlude components from the BOM by either:
|
||||
#
|
||||
# 1) adding a custom field named "Installed" to your components and filling it
|
||||
# with a value of "NU" (Normally Uninstalled).
|
||||
# See netlist.getInterestingComponents(), or
|
||||
#
|
||||
# 2) blacklisting it in any of the three following lists:
|
||||
|
||||
|
||||
# regular expressions which match component 'Reference' fields of components that
|
||||
# are to be excluded from the BOM.
|
||||
excluded_references = [
|
||||
'TP[0-9]+' # all test points
|
||||
]
|
||||
|
||||
|
||||
# regular expressions which match component 'Value' fields of components that
|
||||
# are to be excluded from the BOM.
|
||||
excluded_values = [
|
||||
'MOUNTHOLE',
|
||||
'SCOPETEST',
|
||||
'MOUNT_HOLE',
|
||||
'SOLDER_BRIDGE.*'
|
||||
]
|
||||
|
||||
|
||||
# regular expressions which match component 'Footprint' fields of components that
|
||||
# are to be excluded from the BOM.
|
||||
excluded_footprints = [
|
||||
#'MOUNTHOLE'
|
||||
]
|
||||
|
||||
#-----</Configure>---------------------------------------------------------------
|
||||
|
||||
|
||||
class xmlElement():
|
||||
"""xml element which can represent all nodes of the netlist tree. It can be
|
||||
used to easily generate various output formats by propogating format
|
||||
requests to children recursively.
|
||||
"""
|
||||
def __init__(self, name, parent=None):
|
||||
self.name = name
|
||||
self.attributes = {}
|
||||
self.parent = parent
|
||||
self.chars = ""
|
||||
self.children = []
|
||||
|
||||
def __str__(self):
|
||||
"""String representation of this netlist element
|
||||
|
||||
"""
|
||||
return self.name + "[" + self.chars + "]" + " attr_count:" + str(len(self.attributes))
|
||||
|
||||
def formatXML(self, nestLevel=0, amChild=False):
|
||||
"""Return this element formatted as XML
|
||||
|
||||
Keywords:
|
||||
nestLevel -- increases by one for each level of nesting.
|
||||
amChild -- If set to True, the start of document is not returned.
|
||||
|
||||
"""
|
||||
s = ""
|
||||
|
||||
indent = ""
|
||||
for i in range(nestLevel):
|
||||
indent += " "
|
||||
|
||||
if not amChild:
|
||||
s = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
|
||||
s += indent + "<" + self.name
|
||||
for a in self.attributes:
|
||||
s += " " + a + "=\"" + self.attributes[a] + "\""
|
||||
|
||||
if (len(self.chars) == 0) and (len(self.children) == 0):
|
||||
s += "/>"
|
||||
else:
|
||||
s += ">" + self.chars
|
||||
|
||||
for c in self.children:
|
||||
s += "\n"
|
||||
s += c.formatXML(nestLevel+1, True)
|
||||
|
||||
if (len(self.children) > 0):
|
||||
s += "\n" + indent
|
||||
|
||||
if (len(self.children) > 0) or (len(self.chars) > 0):
|
||||
s += "</" + self.name + ">"
|
||||
|
||||
return s
|
||||
|
||||
def formatHTML(self, amChild=False):
|
||||
"""Return this element formatted as HTML
|
||||
|
||||
Keywords:
|
||||
amChild -- If set to True, the start of document is not returned
|
||||
|
||||
"""
|
||||
s = ""
|
||||
|
||||
if not amChild:
|
||||
s = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
"""
|
||||
|
||||
s += "<tr><td><b>" + self.name + "</b><br>" + self.chars + "</td><td><ul>"
|
||||
for a in self.attributes:
|
||||
s += "<li>" + a + " = " + self.attributes[a] + "</li>"
|
||||
|
||||
s += "</ul></td></tr>\n"
|
||||
|
||||
for c in self.children:
|
||||
s += c.formatHTML(True)
|
||||
|
||||
if not amChild:
|
||||
s += """</table>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
return s
|
||||
|
||||
def addAttribute(self, attr, value):
|
||||
"""Add an attribute to this element"""
|
||||
if type(value) != str: value = value.encode('utf-8')
|
||||
self.attributes[attr] = value
|
||||
|
||||
def setAttribute(self, attr, value):
|
||||
"""Set an attributes value - in fact does the same thing as add
|
||||
attribute
|
||||
|
||||
"""
|
||||
self.attributes[attr] = value
|
||||
|
||||
def setChars(self, chars):
|
||||
"""Set the characters for this element"""
|
||||
self.chars = chars
|
||||
|
||||
def addChars(self, chars):
|
||||
"""Add characters (textual value) to this element"""
|
||||
self.chars += chars
|
||||
|
||||
def addChild(self, child):
|
||||
"""Add a child element to this element"""
|
||||
self.children.append(child)
|
||||
return self.children[len(self.children) - 1]
|
||||
|
||||
def getParent(self):
|
||||
"""Get the parent of this element (Could be None)"""
|
||||
return self.parent
|
||||
|
||||
def getChild(self, name):
|
||||
"""Returns the first child element named 'name'
|
||||
|
||||
Keywords:
|
||||
name -- The name of the child element to return"""
|
||||
for child in self.children:
|
||||
if child.name == name:
|
||||
return child
|
||||
return None
|
||||
|
||||
def getChildren(self, name=None):
|
||||
if name:
|
||||
# return _all_ children named "name"
|
||||
ret = []
|
||||
for child in self.children:
|
||||
if child.name == name:
|
||||
ret.append(child)
|
||||
return ret
|
||||
else:
|
||||
return self.children
|
||||
|
||||
def get(self, elemName, attribute="", attrmatch=""):
|
||||
"""Return the text data for either an attribute or an xmlElement
|
||||
"""
|
||||
if (self.name == elemName):
|
||||
if attribute != "":
|
||||
try:
|
||||
if attrmatch != "":
|
||||
if self.attributes[attribute] == attrmatch:
|
||||
ret = self.chars
|
||||
if type(ret) != str: ret = ret.encode('utf-8')
|
||||
return ret
|
||||
else:
|
||||
ret = self.attributes[attribute]
|
||||
if type(ret) != str: ret = ret.encode('utf-8')
|
||||
return ret
|
||||
except AttributeError:
|
||||
ret = ""
|
||||
if type(ret) != str: ret = ret.encode('utf-8')
|
||||
return ret
|
||||
else:
|
||||
ret = self.chars
|
||||
if type(ret) != str: ret = ret.encode('utf-8')
|
||||
return ret
|
||||
|
||||
for child in self.children:
|
||||
ret = child.get(elemName, attribute, attrmatch)
|
||||
if ret != "":
|
||||
if type(ret) != str: ret = ret.encode('utf-8')
|
||||
return ret
|
||||
|
||||
ret = ""
|
||||
if type(ret) != str: ret = ret.encode('utf-8')
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
class libpart():
|
||||
"""Class for a library part, aka 'libpart' in the xml netlist file.
|
||||
(Components in eeschema are instantiated from library parts.)
|
||||
This part class is implemented by wrapping an xmlElement with accessors.
|
||||
This xmlElement instance is held in field 'element'.
|
||||
"""
|
||||
def __init__(self, xml_element):
|
||||
#
|
||||
self.element = xml_element
|
||||
|
||||
#def __str__(self):
|
||||
# simply print the xmlElement associated with this part
|
||||
#return str(self.element)
|
||||
|
||||
def getLibName(self):
|
||||
return self.element.get("libpart", "lib")
|
||||
|
||||
def getPartName(self):
|
||||
return self.element.get("libpart", "part")
|
||||
|
||||
def getDescription(self):
|
||||
return self.element.get("description")
|
||||
|
||||
def getField(self, name):
|
||||
return self.element.get("field", "name", name)
|
||||
|
||||
def getFieldNames(self):
|
||||
"""Return a list of field names in play for this libpart.
|
||||
"""
|
||||
fieldNames = []
|
||||
fields = self.element.getChild('fields')
|
||||
if fields:
|
||||
for f in fields.getChildren():
|
||||
fieldNames.append( f.get('field','name') )
|
||||
return fieldNames
|
||||
|
||||
def getDatasheet(self):
|
||||
return self.getField("Datasheet")
|
||||
|
||||
def getFootprint(self):
|
||||
return self.getField("Footprint")
|
||||
|
||||
def getAliases(self):
|
||||
"""Return a list of aliases or None"""
|
||||
aliases = self.element.getChild("aliases")
|
||||
if aliases:
|
||||
ret = []
|
||||
children = aliases.getChildren()
|
||||
# grab the text out of each child:
|
||||
for child in children:
|
||||
ret.append( child.get("alias") )
|
||||
return ret
|
||||
return None
|
||||
|
||||
|
||||
class comp():
|
||||
"""Class for a component, aka 'comp' in the xml netlist file.
|
||||
This component class is implemented by wrapping an xmlElement instance
|
||||
with accessors. The xmlElement is held in field 'element'.
|
||||
"""
|
||||
|
||||
def __init__(self, xml_element):
|
||||
self.element = xml_element
|
||||
self.libpart = None
|
||||
|
||||
# Set to true when this component is included in a component group
|
||||
self.grouped = False
|
||||
|
||||
def __eq__(self, other):
|
||||
""" Equivalency operator, remember this can be easily overloaded
|
||||
2 components are equivalent ( i.e. can be grouped
|
||||
if they have same value and same footprint
|
||||
|
||||
Override the component equivalence operator must be done before
|
||||
loading the netlist, otherwise all components will have the original
|
||||
equivalency operator.
|
||||
|
||||
You have to define a comparison module (for instance named myEqu)
|
||||
and add the line;
|
||||
kicad_netlist_reader.comp.__eq__ = myEqu
|
||||
in your bom generator script before calling the netliste reader by something like:
|
||||
net = kicad_netlist_reader.netlist(sys.argv[1])
|
||||
"""
|
||||
result = False
|
||||
if self.getValue() == other.getValue():
|
||||
if self.getFootprint() == other.getFootprint():
|
||||
result = True
|
||||
return result
|
||||
|
||||
def setLibPart(self, part):
|
||||
self.libpart = part
|
||||
|
||||
def getLibPart(self):
|
||||
return self.libpart
|
||||
|
||||
def getPartName(self):
|
||||
return self.element.get("libsource", "part")
|
||||
|
||||
def getLibName(self):
|
||||
return self.element.get("libsource", "lib")
|
||||
|
||||
def setValue(self, value):
|
||||
"""Set the value of this component"""
|
||||
v = self.element.getChild("value")
|
||||
if v:
|
||||
v.setChars(value)
|
||||
|
||||
def getValue(self):
|
||||
return self.element.get("value")
|
||||
|
||||
def getField(self, name, libraryToo=True):
|
||||
"""Return the value of a field named name. The component is first
|
||||
checked for the field, and then the components library part is checked
|
||||
for the field. If the field doesn't exist in either, an empty string is
|
||||
returned
|
||||
|
||||
Keywords:
|
||||
name -- The name of the field to return the value for
|
||||
libraryToo -- look in the libpart's fields for the same name if not found
|
||||
in component itself
|
||||
"""
|
||||
|
||||
field = self.element.get("field", "name", name)
|
||||
if field == "" and libraryToo and self.libpart:
|
||||
field = self.libpart.getField(name)
|
||||
return field
|
||||
|
||||
def getFieldNames(self):
|
||||
"""Return a list of field names in play for this component. Mandatory
|
||||
fields are not included, and they are: Value, Footprint, Datasheet, Ref.
|
||||
The netlist format only includes fields with non-empty values. So if a field
|
||||
is empty, it will not be present in the returned list.
|
||||
"""
|
||||
fieldNames = []
|
||||
fields = self.element.getChild('fields')
|
||||
if fields:
|
||||
for f in fields.getChildren():
|
||||
fieldNames.append( f.get('field','name') )
|
||||
return fieldNames
|
||||
|
||||
def getRef(self):
|
||||
return self.element.get("comp", "ref")
|
||||
|
||||
def getFootprint(self, libraryToo=True):
|
||||
ret = self.element.get("footprint")
|
||||
if ret == "" and libraryToo and self.libpart:
|
||||
ret = self.libpart.getFootprint()
|
||||
return ret
|
||||
|
||||
def getDatasheet(self, libraryToo=True):
|
||||
ret = self.element.get("datasheet")
|
||||
if ret == "" and libraryToo and self.libpart:
|
||||
ret = self.libpart.getDatasheet()
|
||||
return ret
|
||||
|
||||
def getTimestamp(self):
|
||||
return self.element.get("tstamp")
|
||||
|
||||
def getDescription(self):
|
||||
return self.element.get("libsource", "description")
|
||||
|
||||
|
||||
class netlist():
|
||||
""" Kicad generic netlist class. Generally loaded from a kicad generic
|
||||
netlist file. Includes several helper functions to ease BOM creating
|
||||
scripts
|
||||
|
||||
"""
|
||||
def __init__(self, fname=""):
|
||||
"""Initialiser for the genericNetlist class
|
||||
|
||||
Keywords:
|
||||
fname -- The name of the generic netlist file to open (Optional)
|
||||
|
||||
"""
|
||||
self.design = None
|
||||
self.components = []
|
||||
self.libparts = []
|
||||
self.libraries = []
|
||||
self.nets = []
|
||||
|
||||
# The entire tree is loaded into self.tree
|
||||
self.tree = []
|
||||
|
||||
self._curr_element = None
|
||||
|
||||
# component blacklist regexs, made from exluded_* above.
|
||||
self.excluded_references = []
|
||||
self.excluded_values = []
|
||||
self.excluded_footprints = []
|
||||
|
||||
if fname != "":
|
||||
self.load(fname)
|
||||
|
||||
def addChars(self, content):
|
||||
"""Add characters to the current element"""
|
||||
self._curr_element.addChars(content)
|
||||
|
||||
def addElement(self, name):
|
||||
"""Add a new kicad generic element to the list"""
|
||||
if self._curr_element == None:
|
||||
self.tree = xmlElement(name)
|
||||
self._curr_element = self.tree
|
||||
else:
|
||||
self._curr_element = self._curr_element.addChild(
|
||||
xmlElement(name, self._curr_element))
|
||||
|
||||
# If this element is a component, add it to the components list
|
||||
if self._curr_element.name == "comp":
|
||||
self.components.append(comp(self._curr_element))
|
||||
|
||||
# Assign the design element
|
||||
if self._curr_element.name == "design":
|
||||
self.design = self._curr_element
|
||||
|
||||
# If this element is a library part, add it to the parts list
|
||||
if self._curr_element.name == "libpart":
|
||||
self.libparts.append(libpart(self._curr_element))
|
||||
|
||||
# If this element is a net, add it to the nets list
|
||||
if self._curr_element.name == "net":
|
||||
self.nets.append(self._curr_element)
|
||||
|
||||
# If this element is a library, add it to the libraries list
|
||||
if self._curr_element.name == "library":
|
||||
self.libraries.append(self._curr_element)
|
||||
|
||||
return self._curr_element
|
||||
|
||||
def endDocument(self):
|
||||
"""Called when the netlist document has been fully parsed"""
|
||||
# When the document is complete, the library parts must be linked to
|
||||
# the components as they are seperate in the tree so as not to
|
||||
# duplicate library part information for every component
|
||||
for c in self.components:
|
||||
for p in self.libparts:
|
||||
if p.getLibName() == c.getLibName():
|
||||
if p.getPartName() == c.getPartName():
|
||||
c.setLibPart(p)
|
||||
break
|
||||
else:
|
||||
aliases = p.getAliases()
|
||||
if aliases and self.aliasMatch( c.getPartName(), aliases ):
|
||||
c.setLibPart(p)
|
||||
break;
|
||||
|
||||
if not c.getLibPart():
|
||||
logging.error('Missing libpart for ref {}: {}:{}'.format(c.getRef(), c.getLibName(), c.getPartName() ))
|
||||
|
||||
|
||||
def aliasMatch(self, partName, aliasList):
|
||||
for alias in aliasList:
|
||||
if partName == alias:
|
||||
return True
|
||||
return False
|
||||
|
||||
def endElement(self):
|
||||
"""End the current element and switch to its parent"""
|
||||
self._curr_element = self._curr_element.getParent()
|
||||
|
||||
def getDate(self):
|
||||
"""Return the date + time string generated by the tree creation tool"""
|
||||
return self.design.get("date")
|
||||
|
||||
def getSource(self):
|
||||
"""Return the source string for the design"""
|
||||
return self.design.get("source")
|
||||
|
||||
def getTool(self):
|
||||
"""Return the tool string which was used to create the netlist tree"""
|
||||
return self.design.get("tool")
|
||||
|
||||
def gatherComponentFieldUnion(self, components=None):
|
||||
"""Gather the complete 'set' of unique component fields, fields found in any component.
|
||||
"""
|
||||
if not components:
|
||||
components=self.components
|
||||
|
||||
s = set()
|
||||
for c in components:
|
||||
s.update( c.getFieldNames() )
|
||||
|
||||
# omit anything matching any regex in excluded_fields
|
||||
ret = set()
|
||||
for field in s:
|
||||
exclude = False
|
||||
for rex in excluded_fields:
|
||||
if re.match( rex, field ):
|
||||
exclude = True
|
||||
break
|
||||
if not exclude:
|
||||
ret.add(field)
|
||||
|
||||
return ret # this is a python 'set'
|
||||
|
||||
def gatherLibPartFieldUnion(self):
|
||||
"""Gather the complete 'set' of part fields, fields found in any part.
|
||||
"""
|
||||
s = set()
|
||||
for p in self.libparts:
|
||||
s.update( p.getFieldNames() )
|
||||
|
||||
# omit anything matching any regex in excluded_fields
|
||||
ret = set()
|
||||
for field in s:
|
||||
exclude = False
|
||||
for rex in excluded_fields:
|
||||
if re.match( rex, field ):
|
||||
exclude = True
|
||||
break
|
||||
if not exclude:
|
||||
ret.add(field)
|
||||
|
||||
return ret # this is a python 'set'
|
||||
|
||||
def getInterestingComponents(self):
|
||||
"""Return a subset of all components, those that should show up in the BOM.
|
||||
Omit those that should not, by consulting the blacklists:
|
||||
excluded_values, excluded_refs, and excluded_footprints, which hold one
|
||||
or more regular expressions. If any of the the regular expressions match
|
||||
the corresponding field's value in a component, then the component is exluded.
|
||||
"""
|
||||
|
||||
# pre-compile all the regex expressions:
|
||||
del self.excluded_references[:]
|
||||
del self.excluded_values[:]
|
||||
del self.excluded_footprints[:]
|
||||
|
||||
for rex in excluded_references:
|
||||
self.excluded_references.append( re.compile( rex ) )
|
||||
|
||||
for rex in excluded_values:
|
||||
self.excluded_values.append( re.compile( rex ) )
|
||||
|
||||
for rex in excluded_footprints:
|
||||
self.excluded_footprints.append( re.compile( rex ) )
|
||||
|
||||
# the subset of components to return, considered as "interesting".
|
||||
ret = []
|
||||
|
||||
# run each component thru a series of tests, if it passes all, then add it
|
||||
# to the interesting list 'ret'.
|
||||
for c in self.components:
|
||||
exclude = False
|
||||
if not exclude:
|
||||
for refs in self.excluded_references:
|
||||
if refs.match(c.getRef()):
|
||||
exclude = True
|
||||
break;
|
||||
if not exclude:
|
||||
for vals in self.excluded_values:
|
||||
if vals.match(c.getValue()):
|
||||
exclude = True
|
||||
break;
|
||||
if not exclude:
|
||||
for mods in self.excluded_footprints:
|
||||
if mods.match(c.getFootprint()):
|
||||
exclude = True
|
||||
break;
|
||||
|
||||
if not exclude:
|
||||
# This is a fairly personal way to flag DNS (Do Not Stuff). NU for
|
||||
# me means Normally Uninstalled. You can 'or in' another expression here.
|
||||
if c.getField( "Installed" ) == 'NU':
|
||||
exclude = True
|
||||
|
||||
if not exclude:
|
||||
ret.append(c)
|
||||
|
||||
# The key to sort the components in the BOM
|
||||
# This sorts using a natural sorting order (e.g. 100 after 99), and if it wasn't used
|
||||
# the normal sort would place 100 before 99 since it only would look at the first digit.
|
||||
def sortKey( str ):
|
||||
return [ int(t) if t.isdigit() else t.lower()
|
||||
for t in re.split( '(\d+)', str ) ]
|
||||
|
||||
ret.sort(key=lambda g: sortKey(g.getRef()))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def groupComponents(self, components = None):
|
||||
"""Return a list of component lists. Components are grouped together
|
||||
when the value, library and part identifiers match.
|
||||
|
||||
Keywords:
|
||||
components -- is a list of components, typically an interesting subset
|
||||
of all components, or None. If None, then all components are looked at.
|
||||
"""
|
||||
if not components:
|
||||
components = self.components
|
||||
|
||||
groups = []
|
||||
|
||||
# Make sure to start off will all components ungrouped to begin with
|
||||
for c in components:
|
||||
c.grouped = False
|
||||
|
||||
# Group components based on the value, library and part identifiers
|
||||
for c in components:
|
||||
if c.grouped == False:
|
||||
c.grouped = True
|
||||
newgroup = []
|
||||
newgroup.append(c)
|
||||
|
||||
# Check every other ungrouped component against this component
|
||||
# and add to the group as necessary
|
||||
for ci in components:
|
||||
if ci.grouped == False and ci == c:
|
||||
newgroup.append(ci)
|
||||
ci.grouped = True
|
||||
|
||||
# Add the new component group to the groups list
|
||||
groups.append(newgroup)
|
||||
|
||||
# The key to sort the components in the BOM
|
||||
# This sorts using a natural sorting order (e.g. 100 after 99), and if it wasn't used
|
||||
# the normal sort would place 100 before 99 since it only would look at the first digit.
|
||||
def sortKey( str ):
|
||||
return [ int(t) if t.isdigit() else t.lower()
|
||||
for t in re.split( '(\d+)', str ) ]
|
||||
|
||||
for g in groups:
|
||||
g = sorted(g, key=lambda g: sortKey(g.getRef()))
|
||||
|
||||
# Finally, sort the groups to order the references alphabetically
|
||||
groups = sorted(groups, key=lambda group: sortKey(group[0].getRef()))
|
||||
|
||||
return groups
|
||||
|
||||
def getGroupField(self, group, field):
|
||||
"""Return the whatever is known about the given field by consulting each
|
||||
component in the group. If any of them know something about the property/field,
|
||||
then return that first non-blank value.
|
||||
"""
|
||||
for c in group:
|
||||
ret = c.getField(field, False)
|
||||
if ret != '':
|
||||
return ret
|
||||
|
||||
libpart = group[0].getLibPart()
|
||||
if not libpart:
|
||||
return ''
|
||||
|
||||
return libpart.getField(field)
|
||||
|
||||
def getGroupFootprint(self, group):
|
||||
"""Return the whatever is known about the Footprint by consulting each
|
||||
component in the group. If any of them know something about the Footprint,
|
||||
then return that first non-blank value.
|
||||
"""
|
||||
for c in group:
|
||||
ret = c.getFootprint()
|
||||
if ret != "":
|
||||
return ret
|
||||
return group[0].getLibPart().getFootprint()
|
||||
|
||||
def getGroupDatasheet(self, group):
|
||||
"""Return the whatever is known about the Datasheet by consulting each
|
||||
component in the group. If any of them know something about the Datasheet,
|
||||
then return that first non-blank value.
|
||||
"""
|
||||
for c in group:
|
||||
ret = c.getDatasheet()
|
||||
if ret != "":
|
||||
return ret
|
||||
|
||||
if len(group) > 0:
|
||||
return group[0].getLibPart().getDatasheet()
|
||||
else:
|
||||
logging.error("NULL!")
|
||||
return ''
|
||||
|
||||
def formatXML(self):
|
||||
"""Return the whole netlist formatted in XML"""
|
||||
return self.tree.formatXML()
|
||||
|
||||
def formatHTML(self):
|
||||
"""Return the whole netlist formatted in HTML"""
|
||||
return self.tree.formatHTML()
|
||||
|
||||
def load(self, fname):
|
||||
"""Load a kicad generic netlist
|
||||
|
||||
Keywords:
|
||||
fname -- The name of the generic netlist file to open
|
||||
|
||||
"""
|
||||
try:
|
||||
self._reader = sax.make_parser()
|
||||
self._reader.setContentHandler(_gNetReader(self))
|
||||
self._reader.parse(fname)
|
||||
except IOError as e:
|
||||
logging.error("{}: {}".format(__file__, e))
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
|
||||
class _gNetReader(sax.handler.ContentHandler):
|
||||
"""SAX kicad generic netlist content handler - passes most of the work back
|
||||
to the 'netlist' class which builds a complete tree in RAM for the design
|
||||
|
||||
"""
|
||||
def __init__(self, aParent):
|
||||
self.parent = aParent
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
"""Start of a new XML element event"""
|
||||
element = self.parent.addElement(name)
|
||||
|
||||
for name in attrs.getNames():
|
||||
element.addAttribute(name, attrs.getValue(name))
|
||||
|
||||
def endElement(self, name):
|
||||
self.parent.endElement()
|
||||
|
||||
def characters(self, content):
|
||||
# Ignore erroneous white space - ignoreableWhitespace does not get rid
|
||||
# of the need for this!
|
||||
if not content.isspace():
|
||||
self.parent.addChars(content)
|
||||
|
||||
def endDocument(self):
|
||||
"""End of the XML document event"""
|
||||
self.parent.endDocument()
|
Loading…
Reference in New Issue