Repository: pointhi/kicad-footprint-generator Branch: master Commit: 76fedd51e868 Files: 414 Total size: 3.8 MB Directory structure: gitextract_dm0b98jf/ ├── .codeclimate.yml ├── .gitignore ├── .travis.yml ├── AUTHORS.md ├── KicadModTree/ │ ├── FileHandler.py │ ├── KicadFileHandler.py │ ├── ModArgparser.py │ ├── Point.py │ ├── PolygonPoints.py │ ├── Vector.py │ ├── __init__.py │ ├── examples/ │ │ ├── __init__.py │ │ ├── argparse_example.py │ │ ├── padArrayWithOutline.py │ │ ├── params.csv │ │ ├── params.yml │ │ ├── polygon.py │ │ └── simpleFootprint.py │ ├── nodes/ │ │ ├── Footprint.py │ │ ├── Node.py │ │ ├── __init__.py │ │ ├── base/ │ │ │ ├── Arc.py │ │ │ ├── Circle.py │ │ │ ├── Line.py │ │ │ ├── Model.py │ │ │ ├── Pad.py │ │ │ ├── Polygon.py │ │ │ ├── Text.py │ │ │ └── __init__.py │ │ └── specialized/ │ │ ├── ChamferedPad.py │ │ ├── ChamferedPadGrid.py │ │ ├── ExposedPad.py │ │ ├── FilledRect.py │ │ ├── PadArray.py │ │ ├── PolygoneLine.py │ │ ├── RectFill.py │ │ ├── RectLine.py │ │ ├── RingPad.py │ │ ├── Rotation.py │ │ ├── Translation.py │ │ └── __init__.py │ ├── tests/ │ │ ├── __init__.py │ │ ├── datatypes/ │ │ │ ├── __init__.py │ │ │ ├── test_Vector2D.py │ │ │ └── test_Vector3D.py │ │ ├── moduletests/ │ │ │ ├── __init__.py │ │ │ ├── test_arc.py │ │ │ ├── test_exposed_pad.py │ │ │ ├── test_kicad5_padshapes.py │ │ │ ├── test_rotation.py │ │ │ └── test_simple_footprints.py │ │ ├── nodes/ │ │ │ ├── __init__.py │ │ │ └── test_Node.py │ │ └── test.py │ └── util/ │ ├── __init__.py │ ├── geometric_util.py │ ├── kicad_util.py │ └── paramUtil.py ├── LICENSE ├── README.md ├── docs/ │ ├── KicadModTree.nodes.base.rst │ ├── KicadModTree.nodes.rst │ ├── KicadModTree.nodes.specialized.rst │ ├── KicadModTree.rst │ ├── KicadModTree.util.rst │ ├── Makefile │ ├── conf.py │ └── index.rst ├── manage.sh ├── requirements-dev.txt ├── requirements.txt ├── scripts/ │ ├── Battery/ │ │ ├── BatteryHolder.py │ │ ├── BatteryHolder.yml │ │ └── README.txt │ ├── Buttons_Switches/ │ │ ├── make_DIPSwitches.py │ │ ├── rotary_coded_switch.py │ │ └── rotary_coded_switch.yml │ ├── Buzzers_Beepers/ │ │ ├── buzzer_round_tht.py │ │ └── buzzer_round_tht_star_mictronics.csv │ ├── Capacitors_SMD/ │ │ ├── CP_Elec_round.py │ │ ├── CP_Elec_round.yaml │ │ ├── C_Elec_round.py │ │ ├── C_Elec_round.yaml │ │ ├── C_Trimmer_config.yaml │ │ ├── C_Trimmer_factory.py │ │ ├── C_Trimmer_make.py │ │ ├── bump.py │ │ ├── chamfers.py │ │ ├── corners.py │ │ ├── ipc7351B_capae_crystal.yaml │ │ └── tantal and normal smd generator found under SMD_chip_package_rlc-etc │ ├── Capacitors_THT/ │ │ └── make_Capacitors_THT.py │ ├── Chokes_THT/ │ │ └── make_Chokes_THT.py │ ├── Connector/ │ │ ├── Connector_Audio/ │ │ │ └── Jack_3.5mm_Switronic_ST-005-G_horizontal.py │ │ ├── Connector_Harwin/ │ │ │ ├── conn_harwin_m20-781xx45_smd_top_dual_row.py │ │ │ └── m20-89xx.py │ │ ├── Connector_Hirose/ │ │ │ ├── 00-SMD footprint generators can be found in Connector_SMD_single_row_plus_mounting_pad.md │ │ │ ├── conn_ffc_hirose_fh12_smd_side.py │ │ │ ├── conn_hirose_df11_tht_top.py │ │ │ ├── conn_hirose_df12c_ds_smd_top.py │ │ │ ├── conn_hirose_df12e_dp_smd_top.py │ │ │ ├── conn_hirose_df13_tht_side.py │ │ │ ├── conn_hirose_df13_tht_top.py │ │ │ ├── conn_hirose_df13c_smd_top.py │ │ │ ├── conn_hirose_df63_tht_top.py │ │ │ ├── helpers.py │ │ │ └── not_in_official_lib/ │ │ │ ├── df33_straight_pth.py │ │ │ └── df63_angled.py │ │ ├── Connector_IEC_DIN/ │ │ │ └── generate_din41612.py │ │ ├── Connector_JAE/ │ │ │ ├── conn_ffc_jae_ff08.py │ │ │ ├── conn_jae_LY20_tht_side.py │ │ │ ├── conn_jae_LY20_tht_top.py │ │ │ └── helpers.py │ │ ├── Connector_JST/ │ │ │ ├── 00-SMD footprint generators can be found in Connector_SMD_single_row_plus_mounting_pad.md │ │ │ ├── JST-PH-SMT-SIDE_ENTRY.fcstd │ │ │ ├── JST-PH-SMT-TOP_ENTRY.fcstd │ │ │ ├── JST_ZE_top_entry_pad_size.fcstd │ │ │ ├── conn_jst_J2100_tht_side.py │ │ │ ├── conn_jst_J2100_tht_top.py │ │ │ ├── conn_jst_JWPF_tht_top.py │ │ │ ├── conn_jst_NV_tht_top.py │ │ │ ├── conn_jst_PHD_horizontal.py │ │ │ ├── conn_jst_PHD_vertical.py │ │ │ ├── conn_jst_PUD_tht_side.py │ │ │ ├── conn_jst_PUD_tht_top.py │ │ │ ├── conn_jst_VH_tht_side-stabilizer.py │ │ │ ├── conn_jst_VH_tht_side.py │ │ │ ├── conn_jst_VH_tht_top-shrouded.py │ │ │ ├── conn_jst_eh_tht_side.py │ │ │ ├── conn_jst_eh_tht_top.py │ │ │ ├── conn_jst_ph_tht_side.py │ │ │ ├── conn_jst_ph_tht_top.py │ │ │ ├── conn_jst_vh_tht_top.py │ │ │ ├── conn_jst_xh_tht_side.py │ │ │ ├── conn_jst_xh_tht_top.py │ │ │ ├── conn_jst_ze_tht_side.py │ │ │ ├── conn_jst_ze_tht_top.py │ │ │ └── helpers.py │ │ ├── Connector_Molex/ │ │ │ ├── 00-SMD footprint generators can be found in Connector_SMD_single_row_plus_mounting_pad.md │ │ │ ├── conn_ffc_molex_200528.py │ │ │ ├── conn_ffc_molex_502250.py │ │ │ ├── conn_molex_SPOX_tht_side.py │ │ │ ├── conn_molex_SPOX_tht_top.py │ │ │ ├── conn_molex_kk_254_tht_top.py │ │ │ ├── conn_molex_kk_396_tht_top.py │ │ │ ├── conn_molex_mega-fit_tht_side_dual-row.py │ │ │ ├── conn_molex_mega-fit_tht_top_dual_row.py │ │ │ ├── conn_molex_micro-clasp_tht_side.py │ │ │ ├── conn_molex_micro-clasp_tht_top.py │ │ │ ├── conn_molex_micro-fit-3.0_smd_side_dual_row.py │ │ │ ├── conn_molex_micro-fit-3.0_smd_top_dual_row.py │ │ │ ├── conn_molex_micro-fit-3.0_tht_side_dual_row.py │ │ │ ├── conn_molex_micro-fit-3.0_tht_side_single_row.py │ │ │ ├── conn_molex_micro-fit-3.0_tht_top_dual_row.py │ │ │ ├── conn_molex_micro-fit-3.0_tht_top_single_row.py │ │ │ ├── conn_molex_micro-latch_tht_side.py │ │ │ ├── conn_molex_micro-latch_tht_top.py │ │ │ ├── conn_molex_mini-fit-sr_tht_side.py │ │ │ ├── conn_molex_mini-fit-sr_tht_top.py │ │ │ ├── conn_molex_mini-fit-sr_tht_top_dual.py │ │ │ ├── conn_molex_mini-fit_Jr_tht_side_dual-row.py │ │ │ ├── conn_molex_mini-fit_Jr_tht_top_dual-row.py │ │ │ ├── conn_molex_nano-fit_tht_side.py │ │ │ ├── conn_molex_nano-fit_tht_top.py │ │ │ ├── conn_molex_picoblade_tht_side.py │ │ │ ├── conn_molex_picoblade_tht_top.py │ │ │ ├── conn_molex_picoflex_smd_top.py │ │ │ ├── conn_molex_picoflex_tht_top.py │ │ │ ├── conn_molex_sabre_tht_side.py │ │ │ ├── conn_molex_sabre_tht_top.py │ │ │ ├── conn_molex_slimstack-501920.py │ │ │ ├── conn_molex_slimstack-502426.py │ │ │ ├── conn_molex_slimstack-502430.py │ │ │ ├── conn_molex_slimstack-52991.py │ │ │ ├── conn_molex_slimstack-53748.py │ │ │ ├── conn_molex_slimstack-54722.py │ │ │ ├── conn_molex_slimstack-55560.py │ │ │ ├── conn_molex_stackable-linear_tht_top.py │ │ │ └── helpers.py │ │ ├── Connector_PCBEdge/ │ │ │ └── molex_EDGELOCK.py │ │ ├── Connector_PhoenixContact/ │ │ │ ├── config_phoenix_KLCv1.0.yaml │ │ │ ├── config_phoenix_KLCv1.1.yaml │ │ │ ├── config_phoenix_KLCv2.0.yaml │ │ │ ├── config_phoenix_KLCv3.0.yaml │ │ │ ├── config_phoenix_TERA.yaml │ │ │ ├── helpers.py │ │ │ ├── mc.py │ │ │ ├── mc_params.py │ │ │ ├── mstb.py │ │ │ └── mstb_params.py │ │ ├── Connector_SMD_single_row_plus_mounting_pad/ │ │ │ ├── conn_hirose.yaml │ │ │ ├── conn_jst.yaml │ │ │ ├── conn_molex.yaml │ │ │ ├── helpers.py │ │ │ └── smd_single_row_plus_mounting_pad.py │ │ ├── Connector_Samtec/ │ │ │ ├── conn_samtec_LSHM_smd_top.py │ │ │ ├── conn_samtec_hle.py │ │ │ ├── helpers.py │ │ │ ├── mecf_connector.py │ │ │ └── mecf_socket.py │ │ ├── Connector_Stocko/ │ │ │ └── conn_Stocko_MKS_16xx.py │ │ ├── Connector_TE-Connectivity/ │ │ │ ├── conn_ffc_te_84952-84953.py │ │ │ ├── conn_fpc_te_1734839.py │ │ │ ├── conn_te_826576.py │ │ │ ├── conn_te_mate-n-lock_tht_side.py │ │ │ ├── conn_te_mate-n-lock_tht_top.py │ │ │ └── helpers.py │ │ ├── Connector_Wago/ │ │ │ ├── conn_wago_734_horizontal.py │ │ │ ├── conn_wago_734_vertical.py │ │ │ └── helpers.py │ │ ├── Connector_Wire/ │ │ │ ├── Research/ │ │ │ │ └── sources.md │ │ │ ├── solder_wire_tht.py │ │ │ └── wire_MC_Flexivolt.yaml │ │ ├── Connector_Wuerth/ │ │ │ └── wuerth_6480xx11622.py │ │ ├── conn_config_KLCv2.yaml │ │ └── conn_config_KLCv3.yaml │ ├── Connector_PinSocket/ │ │ ├── canvas.py │ │ ├── cq_base_parameters.py │ │ ├── main_generator.py │ │ ├── parameters.py │ │ ├── parameters.yaml │ │ └── socket_strips.py │ ├── Connectors_DSub/ │ │ └── make_dsubs.py │ ├── Converter_DCDC/ │ │ ├── Converter_DCDC.py │ │ ├── Converter_DCDC.yml │ │ ├── XP_Power_SF_THT.py │ │ └── conv_config_KLCv3.yaml │ ├── Crystals_Resonators_SMD/ │ │ └── make_crystal_smd.py │ ├── Crystals_Resonators_THT/ │ │ └── make_crystal.py │ ├── Diodes_SMD/ │ │ └── generator found under SMD_chip_package_rlc-etc │ ├── Diodes_THT/ │ │ └── make_Diodes_THT.py │ ├── Fuse/ │ │ ├── ptc-fuse-tht.py │ │ └── ptc-fuse-tht.yaml │ ├── Inductor_SMD/ │ │ ├── Inductor_SMD.py │ │ └── Inductor_SMD.yml │ ├── Inductors/ │ │ ├── Choke_Schaffner_RNXXX.py │ │ ├── Murata_DEM35xxC.py │ │ ├── bourns-srn.py │ │ ├── generator for normal packages found under SMD_chip_package_rlc-etc │ │ ├── vishay_IHSM.py │ │ ├── we-hci.py │ │ ├── we-hcm.py │ │ └── we-mapi.py │ ├── LEDs_SMD/ │ │ ├── generator for normal packages found under SMD_chip_package_rlc-etc │ │ ├── plcc4.py │ │ ├── plcc4.yml │ │ └── smlvn6.py │ ├── LEDs_THT/ │ │ └── make_LEDs_THT.py │ ├── Mounting_Hardware/ │ │ ├── mounting_hole.py │ │ ├── wuerth_smt_spacer.py │ │ └── wuerth_smt_spacer.yaml │ ├── Mounting_Holes/ │ │ └── mounting_hole_long.yaml │ ├── Multicomp/ │ │ ├── connectors_multicomp_mc9a12.py │ │ ├── connectors_multicomp_mc9a22.py │ │ └── create_connectors_multicomp.sh │ ├── Oscillators_SMD/ │ │ └── make_oscillators.py │ ├── Packages/ │ │ ├── Package_BGA/ │ │ │ ├── bga.yaml │ │ │ ├── bga_xilinx.yaml │ │ │ ├── csp.yaml │ │ │ ├── ipc_7351b_bga_land_patterns.yaml │ │ │ ├── ipc_bga_generator.py │ │ │ └── test_ipc.yaml │ │ ├── Package_DIP/ │ │ │ └── make_DIP_footprints.py │ │ ├── Package_Gullwing__QFP_SOIC_SO/ │ │ │ ├── Readme.md │ │ │ ├── ipc_gullwing_generator.py │ │ │ └── size_definitions/ │ │ │ ├── eqfp.yaml │ │ │ ├── hsoic.yaml │ │ │ ├── hsop.yaml │ │ │ ├── htsop.yaml │ │ │ ├── htssop.yaml │ │ │ ├── hvssop.yaml │ │ │ ├── infineon.yaml │ │ │ ├── lqfp.yaml │ │ │ ├── mqfp.yaml │ │ │ ├── msop.yaml │ │ │ ├── pqfp.yaml │ │ │ ├── sc-74.yaml │ │ │ ├── so.yaml │ │ │ ├── soic.yaml │ │ │ ├── soj.yaml │ │ │ ├── sop.yaml │ │ │ ├── sot.yaml │ │ │ ├── sso.yaml │ │ │ ├── ssop.yaml │ │ │ ├── test_hidden_deleted_pins.yaml │ │ │ ├── test_so.yaml │ │ │ ├── tqfp.yaml │ │ │ ├── tsop-i.yaml │ │ │ ├── tsop-ii.yaml │ │ │ ├── tsot.yaml │ │ │ ├── tssop.yaml │ │ │ ├── vqfp.yaml │ │ │ └── vssop.yaml │ │ ├── Package_NoLead__DFN_QFN_LGA_SON/ │ │ │ ├── Readme.md │ │ │ ├── ipc_noLead_generator.py │ │ │ ├── qfn.py │ │ │ ├── qfn.yml │ │ │ └── size_definitions/ │ │ │ ├── MicroSiP.yaml │ │ │ ├── csp.yaml │ │ │ ├── dfn.yaml │ │ │ ├── hvson8.yaml │ │ │ ├── lfcsp.yaml │ │ │ ├── lga.yaml │ │ │ ├── oscillator.yaml │ │ │ ├── qfn/ │ │ │ │ ├── hvqfn.yaml │ │ │ │ ├── qfn-1x.yaml │ │ │ │ ├── qfn-20.yaml │ │ │ │ ├── qfn-24.yaml │ │ │ │ ├── qfn-28.yaml │ │ │ │ ├── qfn-3x.yaml │ │ │ │ ├── qfn-4x.yaml │ │ │ │ ├── qfn-5x.yaml │ │ │ │ ├── qfn-64_9x9.yaml │ │ │ │ ├── qfn-6x.yaml │ │ │ │ ├── qfn-7x.yaml │ │ │ │ ├── qfn-mini-circuits.yaml │ │ │ │ ├── qfn-onsemi-vct.yml │ │ │ │ ├── qfn-other-pincounts.yaml │ │ │ │ ├── qfn_texas.yaml │ │ │ │ ├── special_qfn.yaml │ │ │ │ ├── tqfn.yaml │ │ │ │ ├── ufqfpn.yaml │ │ │ │ ├── uqfn.yaml │ │ │ │ ├── vqfn.yaml │ │ │ │ └── wqfn.yaml │ │ │ ├── vson.yaml │ │ │ ├── wdfn-8.yml │ │ │ └── wson.yaml │ │ ├── Package_PLCC/ │ │ │ ├── ipc_plcc_jLead_generator.py │ │ │ └── plcc_jLead_definitions.yaml │ │ ├── TO_SOT_Packages_SMD/ │ │ │ ├── DPAK.py │ │ │ ├── DPAK_README.md │ │ │ ├── DPAK_config.yaml │ │ │ └── make_DPAK.py │ │ ├── TO_SOT_THT/ │ │ │ ├── TO_SOT_THT_generate.py │ │ │ ├── TO_THT_packages.py │ │ │ └── tools.py │ │ ├── ipc_definitions.yaml │ │ ├── package_config_KLCv3.yaml │ │ └── utils/ │ │ └── ep_handling_utils.py │ ├── PadGenerator/ │ │ └── RingPad.py │ ├── Potentiometers/ │ │ ├── make_Potentiometer_SMD.py │ │ ├── make_Potentiometer_THT.py │ │ ├── slide_Potentiometer.py │ │ └── slide_Potentiometer.yaml │ ├── Recom_DCDC/ │ │ └── Recom_SIP.py │ ├── ResistorArrays_SIP_THT/ │ │ └── make_Resistor_array_SIP.py │ ├── Resistor_THT/ │ │ └── make_Resistors_THT.py │ ├── Resistors_SMD/ │ │ ├── README.md │ │ ├── generator found under SMD_chip_package_rlc-etc │ │ └── smd_chip_resistors_smd.csv │ ├── SMD_chip_package_rlc-etc/ │ │ ├── SMD_chip_devices.yaml │ │ ├── SMD_chip_package_rlc-etc.py │ │ ├── config_KLCv3.0.yaml │ │ ├── ipc7351B_smd_two_terminal_chip.yaml │ │ ├── ipc_smd_two_terminal_chip.yaml │ │ └── size_definitions/ │ │ ├── size_capacitor_chip_devices.yaml │ │ ├── size_default_chip_devices.yaml │ │ ├── size_default_chip_devices_smaller_0402.yaml │ │ ├── size_default_chip_devices_smaller_0603.yaml │ │ ├── size_diode.yaml │ │ ├── size_fuse.yaml │ │ ├── size_inductor.yaml │ │ ├── size_resistor.yaml │ │ ├── size_tantal.yaml │ │ └── size_wide_body_chip_resistor.yaml │ ├── Shielding/ │ │ ├── laird_technologies_smd_shielding.kicad_mod.yaml │ │ ├── smd_shielding.py │ │ ├── wuerth_electronic_smd_shielding.py │ │ ├── wuerth_electronic_tht_shielding.py │ │ └── wuerth_smd_shielding.kicad_mod.yaml │ ├── Socket/ │ │ ├── 3M_Textool.py │ │ └── 3M_Textool.yaml │ ├── TerminalBlock_4Ucon/ │ │ └── make_TerminalBlock_4Ucon.py │ ├── TerminalBlock_Altech/ │ │ ├── Altech.py │ │ └── Altech.yml │ ├── TerminalBlock_MetzConnect/ │ │ ├── make_SingleTerminalBlock_MetzConnect.py │ │ └── make_TerminalBlock_MetzConnect.py │ ├── TerminalBlock_Philmore/ │ │ └── make_TerminalBlock_Philmore.py │ ├── TerminalBlock_Phoenix/ │ │ └── make_TerminalBlock_Phoenix.py │ ├── TerminalBlock_RND/ │ │ └── make_TerminalBlock_RND.py │ ├── TerminalBlock_TE-Connectivity/ │ │ └── make_TerminalBlock_TE-Connectivity.py │ ├── TerminalBlock_WAGO/ │ │ └── make_TerminalBlock_WAGO.py │ ├── Vigortronix/ │ │ └── vigotronix.py │ ├── example_kicadmodtree_script.py │ ├── general/ │ │ ├── StandardBox.py │ │ ├── new more powerfull generator found under SMD_chip_package_rlc-etc │ │ └── smd_chip.py │ ├── pin-headers_socket-strips/ │ │ ├── make_idc_headers.py │ │ ├── make_pin_headers.py │ │ └── make_socket_strips.py │ └── tools/ │ ├── dict_tools.py │ ├── drawing_tools.py │ ├── footprint_global_properties.py │ ├── footprint_keepout_area.py │ ├── footprint_scripts_DIP.py │ ├── footprint_scripts_LEDs.py │ ├── footprint_scripts_crystals.py │ ├── footprint_scripts_dsub.py │ ├── footprint_scripts_pin_headers.py │ ├── footprint_scripts_potentiometers.py │ ├── footprint_scripts_resistorlike.py │ ├── footprint_scripts_sip.py │ ├── footprint_scripts_terminal_blocks.py │ ├── footprint_text_fields.py │ ├── global_config_files/ │ │ ├── config_KLCv1.0.yaml │ │ ├── config_KLCv2.0.yaml │ │ ├── config_KLCv3.0.yaml │ │ └── config_Tera.yaml │ ├── ipc_pad_size_calculators.py │ ├── pad_number_generators.py │ └── quad_dual_pad_border.py ├── setup.py └── tox.ini ================================================ FILE CONTENTS ================================================ ================================================ FILE: .codeclimate.yml ================================================ engines: duplication: enabled: true config: languages: - python fixme: enabled: true radon: enabled: true pep8: enabled: true shellcheck: enabled: true ratings: paths: - "**.py" - "**.sh" exclude_paths: - doc/**/* - scripts/**/* - "**/tests/" ================================================ FILE: .gitignore ================================================ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover .hypothesis/ # Sphinx documentation docs/_build/ # pyenv .python-version # kicad specific files *.kicad_mod *.pretty/ ================================================ FILE: .travis.yml ================================================ sudo: false cache: - pip - directories: - $HOME/.cache/pip language: python python: - "2.7" - "3.4" - "3.5" - "3.6" - "3.7" install: - ./manage.sh update_dev_packages script: - ./manage.sh pep8_check - ./manage.sh unit_tests - ./manage.sh py_test_coverage ================================================ FILE: AUTHORS.md ================================================ **Maintainer:** * Thomas Pointhuber @pointhi * Rene Pöschl, @poeschlr * @evanshultz **Contributors:** People who have submitted patches, reported bugs, consulted features or generally made KicadModTree better * Oliver, @SchrodingersGat * Jan W. Krieger, @jkriege2 * Frank, @Frankkkkk * @Hackscribble * @stoth * Patrick Pelletier, @ppelleti * @DASFrank * Dominik Baack, @matyro * Jordi Pakey-Rodriguez, @0xdec * George, @grob6000 * Tobias Müller, @twam * Terje Io, @terjeio * Frank Severinsen, @Shackmeister * @robertlong13 * Julien Cassette, @jcassette * Trevor Vannoy, @tvannoy * Kari Hautio, @kh4 * Stefan, @Misca1234 * Antonio Vazquez, @antoniovazquezblanco * Hendrik v. Raven, @lorem-ipsum * Asuki Kono, @asukiaaa * Xathar, @jneiva08 * @matthuszagh * @ferdymercury * @jhalmen * @herostrat * @fauxpark * @matthijskooijman * Clara Hobbs, @Ratfink * @MRQ * Stefan Krüger, @s-light * John Whitmore, @johnfwhitmore * Daniel Mack, @zonque * @dominformant * @tpambor * @nivekg * Joel, @myfreescalewebpage * JonRB, @eeyrjmr * Alexander Ransmann, @cronJ * Christian Schlüter, @chschlue * Chase Patterson, @chapatt * Rolf Schäuble, @rschaeuble * @penoud * @ki5libs * @fvollmer * @cp-aquila * Anders Wallin, @aewallin * Jonas Schievink, @jonas-schievink * Diego Herranz, @diegoherranz * Alexandre Oliveira, @RockyTV * Konstantin Oblaukhov, @ObKo * Jesper, @JeppeSRC * Jacob E. F. Overgaard @JacobEFO * Ed Peguillan III, @yankee14 * Thomas Schmid, @rckTom * @mitch354 * Jan Krueger, @einball * @dogtopus * Darrell Harmon, @dlharmon * David Imhoff, @dimhoff * marble, @cyber-murmel * @chemicstry * @awygle * @TiZed * Sean Leavey, @SeanDS * @Schlumpf * Daniel Giesbrecht, @DanSGiesbrecht * Caleb Reister, @calebreister * Greg Cormier, @gcormier * Ilya Elenskiy, @EvilMav * Mathias Walter, @tolot27 * Michael Munch, @Munken * @waschhauser ================================================ FILE: KicadModTree/FileHandler.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, import sys import io class FileHandler(object): r"""some basic methods to write footprints, and which is the base class of footprint writer implementations :param kicad_mod: Main object representing the footprint :type kicad_mod: ``KicadModTree.Footprint`` :Example: >>> from KicadModTree import * >>> kicad_mod = Footprint("example_footprint") >>> file_handler = KicadFileHandler(kicad_mod) # KicadFileHandler is a implementation of FileHandler >>> file_handler.writeFile('example_footprint.kicad_mod') """ def __init__(self, kicad_mod): self.kicad_mod = kicad_mod def writeFile(self, filename, **kwargs): r"""Write the output of FileHandler.serialize to a file :param filename: path of the output file :type filename: ``str`` :Example: >>> from KicadModTree import * >>> kicad_mod = Footprint("example_footprint") >>> file_handler = KicadFileHandler(kicad_mod) # KicadFileHandler is a implementation of FileHandler >>> file_handler.writeFile('example_footprint.kicad_mod') """ with io.open(filename, "w", newline='\n') as f: output = self.serialize(**kwargs) # convert to unicode if running python2 if sys.version_info[0] == 2 and type(output) != unicode: output = unicode(output, "utf-8") f.write(output) f.close() def serialize(self, **kwargs): r"""Get a valid string representation of the footprint in the specified format :Example: >>> from KicadModTree import * >>> kicad_mod = Footprint("example_footprint") >>> file_handler = KicadFileHandler(kicad_mod) # KicadFileHandler is a implementation of FileHandler >>> print(file_handler.serialize()) """ raise NotImplementedError("serialize has to be implemented by child class") ================================================ FILE: KicadModTree/KicadFileHandler.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, from KicadModTree.FileHandler import FileHandler from KicadModTree.util.kicad_util import * from KicadModTree.nodes.base.Pad import Pad # TODO: why .KicadModTree is not enough? from KicadModTree.nodes.base.Arc import Arc from KicadModTree.nodes.base.Circle import Circle from KicadModTree.nodes.base.Line import Line from KicadModTree.nodes.base.Polygon import Polygon DEFAULT_LAYER_WIDTH = {'F.SilkS': 0.12, 'B.SilkS': 0.12, 'F.Fab': 0.10, 'B.Fab': 0.10, 'F.CrtYd': 0.05, 'B.CrtYd': 0.05} DEFAULT_WIDTH_POLYGON_PAD = 0 DEFAULT_WIDTH = 0.15 def _get_layer_width(layer, width=None): if width is not None: return width else: return DEFAULT_LAYER_WIDTH.get(layer, DEFAULT_WIDTH) class KicadFileHandler(FileHandler): r"""Implementation of the FileHandler for .kicad_mod files :param kicad_mod: Main object representing the footprint :type kicad_mod: ``KicadModTree.Footprint`` :Example: >>> from KicadModTree import * >>> kicad_mod = Footprint("example_footprint") >>> file_handler = KicadFileHandler(kicad_mod) >>> file_handler.writeFile('example_footprint.kicad_mod') """ def __init__(self, kicad_mod): FileHandler.__init__(self, kicad_mod) def serialize(self, **kwargs): r"""Get a valid string representation of the footprint in the .kicad_mod format :Example: >>> from KicadModTree import * >>> kicad_mod = Footprint("example_footprint") >>> file_handler = KicadFileHandler(kicad_mod) >>> print(file_handler.serialize()) """ sexpr = ['module', self.kicad_mod.name, ['layer', 'F.Cu'], ['tedit', formatTimestamp(kwargs.get('timestamp'))], SexprSerializer.NEW_LINE ] # NOQA if self.kicad_mod.description: sexpr.append(['descr', self.kicad_mod.description]) sexpr.append(SexprSerializer.NEW_LINE) if self.kicad_mod.tags: sexpr.append(['tags', self.kicad_mod.tags]) sexpr.append(SexprSerializer.NEW_LINE) if self.kicad_mod.attribute: sexpr.append(['attr', self.kicad_mod.attribute]) sexpr.append(SexprSerializer.NEW_LINE) if self.kicad_mod.maskMargin: sexpr.append(['solder_mask_margin', self.kicad_mod.maskMargin]) sexpr.append(SexprSerializer.NEW_LINE) if self.kicad_mod.pasteMargin: sexpr.append(['solder_paste_margin', self.kicad_mod.pasteMargin]) sexpr.append(SexprSerializer.NEW_LINE) if self.kicad_mod.pasteMarginRatio: sexpr.append(['solder_paste_ratio', self.kicad_mod.pasteMarginRatio]) sexpr.append(SexprSerializer.NEW_LINE) sexpr.extend(self._serializeTree()) return str(SexprSerializer(sexpr)) def _serializeTree(self): nodes = self.kicad_mod.serialize() grouped_nodes = {} for single_node in nodes: node_type = single_node.__class__.__name__ current_nodes = grouped_nodes.get(node_type, []) current_nodes.append(single_node) grouped_nodes[node_type] = current_nodes sexpr = [] # serialize initial text nodes if 'Text' in grouped_nodes: reference_nodes = list(filter(lambda node: node.type == 'reference', grouped_nodes['Text'])) for node in reference_nodes: sexpr.append(self._serialize_Text(node)) sexpr.append(SexprSerializer.NEW_LINE) grouped_nodes['Text'].remove(node) value_nodes = list(filter(lambda node: node.type == 'value', grouped_nodes['Text'])) for node in value_nodes: sexpr.append(self._serialize_Text(node)) sexpr.append(SexprSerializer.NEW_LINE) grouped_nodes['Text'].remove(node) for key, value in sorted(grouped_nodes.items()): # check if key is a base node, except Model if key not in {'Arc', 'Circle', 'Line', 'Pad', 'Polygon', 'Text'}: continue # render base nodes for node in value: sexpr.append(self._callSerialize(node)) sexpr.append(SexprSerializer.NEW_LINE) # serialize 3D Models at the end if grouped_nodes.get('Model'): for node in grouped_nodes.get('Model'): sexpr.append(self._serialize_Model(node)) sexpr.append(SexprSerializer.NEW_LINE) return sexpr def _callSerialize(self, node): ''' call the corresponding method to serialize the node ''' method_type = node.__class__.__name__ method_name = "_serialize_{0}".format(method_type) if hasattr(self, method_name): return getattr(self, method_name)(node) else: exception_string = "{name} (node) not found, cannot serialized the node of type {type}" raise NotImplementedError(exception_string.format(name=method_name, type=method_type)) def _serialize_ArcPoints(self, node): # in KiCAD, some file attributes of Arc are named not in the way of their real meaning center_pos = node.getRealPosition(node.center_pos) end_pos = node.getRealPosition(node.start_pos) return [ ['start', center_pos.x, center_pos.y], ['end', end_pos.x, end_pos.y], ['angle', node.angle] ] def _serialize_Arc(self, node): sexpr = ['fp_arc'] sexpr += self._serialize_ArcPoints(node) sexpr += [ ['layer', node.layer], ['width', _get_layer_width(node.layer, node.width)] ] # NOQA return sexpr def _serialize_CirclePoints(self, node): center_pos = node.getRealPosition(node.center_pos) end_pos = node.getRealPosition(node.center_pos + (node.radius, 0)) return [ ['center', center_pos.x, center_pos.y], ['end', end_pos.x, end_pos.y] ] def _serialize_Circle(self, node): sexpr = ['fp_circle'] sexpr += self._serialize_CirclePoints(node) sexpr += [ ['layer', node.layer], ['width', _get_layer_width(node.layer, node.width)] ] # NOQA return sexpr def _serialize_LinePoints(self, node): start_pos = node.getRealPosition(node.start_pos) end_pos = node.getRealPosition(node.end_pos) return [ ['start', start_pos.x, start_pos.y], ['end', end_pos.x, end_pos.y] ] def _serialize_Line(self, node): start_pos = node.getRealPosition(node.start_pos) end_pos = node.getRealPosition(node.end_pos) sexpr = ['fp_line'] sexpr += self._serialize_LinePoints(node) sexpr += [ ['layer', node.layer], ['width', _get_layer_width(node.layer, node.width)] ] # NOQA return sexpr def _serialize_Text(self, node): sexpr = ['fp_text', node.type, node.text] position, rotation = node.getRealPosition(node.at, node.rotation) if rotation: sexpr.append(['at', position.x, position.y, rotation]) else: sexpr.append(['at', position.x, position.y]) sexpr.append(['layer', node.layer]) if node.hide: sexpr.append('hide') sexpr.append(SexprSerializer.NEW_LINE) effects = [ 'effects', ['font', ['size', node.size.x, node.size.y], ['thickness', node.thickness]]] if node.mirror: effects.append(['justify', 'mirror']) sexpr.append(effects) sexpr.append(SexprSerializer.NEW_LINE) return sexpr def _serialize_Model(self, node): sexpr = ['model', node.filename, SexprSerializer.NEW_LINE, ['at', ['xyz', node.at.x, node.at.y, node.at.z]], SexprSerializer.NEW_LINE, ['scale', ['xyz', node.scale.x, node.scale.y, node.scale.z]], SexprSerializer.NEW_LINE, ['rotate', ['xyz', node.rotate.x, node.rotate.y, node.rotate.z]], SexprSerializer.NEW_LINE ] # NOQA return sexpr def _serialize_CustomPadPrimitives(self, pad): all_primitives = [] for p in pad.primitives: all_primitives.extend(p.serialize()) grouped_nodes = {} for single_node in all_primitives: node_type = single_node.__class__.__name__ current_nodes = grouped_nodes.get(node_type, []) current_nodes.append(single_node) grouped_nodes[node_type] = current_nodes sexpr_primitives = [] for key, value in sorted(grouped_nodes.items()): # check if key is a base node, except Model if key not in {'Arc', 'Circle', 'Line', 'Pad', 'Polygon', 'Text'}: continue # render base nodes for p in value: if isinstance(p, Polygon): sp = ['gr_poly', self._serialize_PolygonPoints(p, newline_after_pts=True) ] # NOQA elif isinstance(p, Line): sp = ['gr_line'] + self._serialize_LinePoints(p) elif isinstance(p, Circle): sp = ['gr_circle'] + self._serialize_CirclePoints(p) elif isinstance(p, Arc): sp = ['gr_arc'] + self._serialize_ArcPoints(p) else: raise TypeError('Unsuported type of primitive for custom pad.') sp.append(['width', DEFAULT_WIDTH_POLYGON_PAD if p.width is None else p.width]) sexpr_primitives.append(sp) sexpr_primitives.append(SexprSerializer.NEW_LINE) return sexpr_primitives def _serialize_Pad(self, node): sexpr = ['pad', node.number, node.type, node.shape] position, rotation = node.getRealPosition(node.at, node.rotation) if not rotation % 360 == 0: sexpr.append(['at', position.x, position.y, rotation]) else: sexpr.append(['at', position.x, position.y]) sexpr.append(['size', node.size.x, node.size.y]) if node.type in [Pad.TYPE_THT, Pad.TYPE_NPTH]: if node.drill.x == node.drill.y: sexpr.append(['drill', node.drill.x]) else: sexpr.append(['drill', 'oval', node.drill.x, node.drill.y]) sexpr.append(['layers'] + node.layers) if node.shape == Pad.SHAPE_ROUNDRECT: sexpr.append(['roundrect_rratio', node.radius_ratio]) if node.shape == Pad.SHAPE_CUSTOM: # gr_line, gr_arc, gr_circle or gr_poly sexpr.append(SexprSerializer.NEW_LINE) sexpr.append(['options', ['clearance', node.shape_in_zone], ['anchor', node.anchor_shape] ]) # NOQA sexpr.append(SexprSerializer.NEW_LINE) sexpr_primitives = self._serialize_CustomPadPrimitives(node) sexpr.append(['primitives', SexprSerializer.NEW_LINE] + sexpr_primitives) if node.solder_paste_margin_ratio != 0 or node.solder_mask_margin != 0 or node.solder_paste_margin != 0: sexpr.append(SexprSerializer.NEW_LINE) if node.solder_mask_margin != 0: sexpr.append(['solder_mask_margin', node.solder_mask_margin]) if node.solder_paste_margin_ratio != 0: sexpr.append(['solder_paste_margin_ratio', node.solder_paste_margin_ratio]) if node.solder_paste_margin != 0: sexpr.append(['solder_paste_margin', node.solder_paste_margin]) return sexpr def _serialize_PolygonPoints(self, node, newline_after_pts=False): node_points = ['pts'] if newline_after_pts: node_points.append(SexprSerializer.NEW_LINE) points_appended = 0 for n in node.nodes: if points_appended >= 4: points_appended = 0 node_points.append(SexprSerializer.NEW_LINE) points_appended += 1 n_pos = node.getRealPosition(n) node_points.append(['xy', n_pos.x, n_pos.y]) return node_points def _serialize_Polygon(self, node): node_points = self._serialize_PolygonPoints(node) sexpr = ['fp_poly', node_points, ['layer', node.layer], ['width', _get_layer_width(node.layer, node.width)] ] # NOQA return sexpr ================================================ FILE: KicadModTree/ModArgparser.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2017 by Thomas Pointhuber, import sys import argparse import csv try: import yaml YAML_AVAILABLE = True except ImportError: YAML_AVAILABLE = False class ParserException(Exception): def __itruediv__(self, *args, **kwargs): Exception.__init__(self, *args, **kwargs) class ModArgparser(object): r"""A general data loading class, which allows us to specify parts using .yml or .csv files. Using this class allows us to seperate between the implementation of a footprint generator, and the data which represents a single footprint. To do so, we need to define which parameters are expected in those data-files. To improve the usablity of this class, it is able to do type checks of provided parameters, as well as defining default values and do a simple check if a parameter can be considered as required or optional. :param footprint_function: A function which is called for every footprint we want to generate :type footprint_function: ``function reference`` :Example: >>> from KicadModTree import * >>> def footprint_gen(args): ... print("create footprint: {}".format(args['name'])) ... >>> parser = ModArgparser(footprint_gen) >>> parser.add_parameter("name", type=str, required=True) # the root node of .yml files is parsed as name >>> parser.add_parameter("datasheet", type=str, required=False) >>> parser.add_parameter("courtyard", type=float, required=False, default=0.25) >>> parser.add_parameter("pincount", type=int, required=True) >>> parser.run() # now run our script which handles the whole part of parsing the files """ def __init__(self, footprint_function): self._footprint_function = footprint_function self._params = {} def add_parameter(self, name, **kwargs): r"""Add a parameter to the ModArgparser :param name: name of the argument :param \**kwargs: See below :type name: ``str`` :Keyword Arguments: * *type* (``type``) -- type of the argument * *required* (``bool``) -- is the argument required or optional * *default* -- a default value which is used when there is no value defined :Example: >>> from KicadModTree import * >>> def footprint_gen(args): ... print("create footprint: {}".format(args['name'])) ... >>> parser = ModArgparser(footprint_gen) >>> parser.add_parameter("name", type=str, required=True) # the root node of .yml files is parsed as name >>> parser.add_parameter("datasheet", type=str, required=False) >>> parser.add_parameter("courtyard", type=float, required=False, default=0.25) """ self._params[name] = kwargs def run(self): r"""Execute the ModArgparser and run all tasks defined via the commandline arguments of this script This method parses the commandline arguments to determine which actions to take. Beside of parsing .yml and .csv files, it also allows us to output example files. >>> from KicadModTree import * >>> def footprint_gen(args): ... print("create footprint: {}".format(args['name'])) ... >>> parser = ModArgparser(footprint_gen) >>> parser.add_parameter("name", type=str, required=True) # the root node of .yml files is parsed as name >>> parser.run() # now run our script which handles the whole part of parsing the files """ parser = argparse.ArgumentParser(description='Parse footprint defintion file(s) and create matching footprints') parser.add_argument('files', metavar='file', type=str, nargs='*', help='.yml or .csv files which contains data') parser.add_argument('-v', '--verbose', help='show some additional information', action='store_true') # TODO parser.add_argument('--print_yml', help='print example .yml file', action='store_true') parser.add_argument('--print_csv', help='print example .csv file', action='store_true') # TODO: allow writing into sub dir args = parser.parse_args() if args.print_yml: self._print_example_yml() return if args.print_csv: self._print_example_csv() return if len(args.files) == 0: parser.print_help() return for filepath in args.files: print("use file: {0}".format(filepath)) if filepath.endswith('.yml') or filepath.endswith('.yaml'): self._parse_and_execute_yml(filepath) elif filepath.endswith('.csv'): self._parse_and_execute_csv(filepath) else: print("unexpected filetype: {0}".format(filepath)) def _parse_and_execute_yml(self, filepath): if not YAML_AVAILABLE: print("pyyaml not available!") sys.exit(1) with open(filepath, 'r') as stream: try: parsed = yaml.safe_load(stream) # parse file if parsed is None: print("empty file!") return for footprint in parsed: kwargs = parsed.get(footprint) # name is a reserved key if 'name' in kwargs: print("ERROR: name is already used for root name!") continue kwargs['name'] = footprint self._execute_script(**kwargs) # now we can execute the script except yaml.YAMLError as exc: print(exc) def _create_example_data_required(self, **kwargs): params = {} for k, v in self._params.items(): if kwargs.get('include_name', False) is False and k == "name": continue if v.get('required', False): params[k] = self._create_example_datapoint(v.get('type', str), v.get('default')) return params def _create_example_data_full(self, **kwargs): params = {} for k, v in self._params.items(): if kwargs.get('include_name', False) is False and k == "name": continue params[k] = self._create_example_datapoint(v.get('type', str), v.get('default')) return params def _create_example_datapoint(self, type, default): if default: return type(default) if type is bool: return False elif type is int: return 0 elif type is float: return 0.0 elif type is str: return "some string" else: return "??" def _print_example_yml(self): if not YAML_AVAILABLE: print("pyyaml not available!") sys.exit(1) data = {'footprint_required': self._create_example_data_required(), 'footprint_full': self._create_example_data_full()} print(yaml.dump(data, default_flow_style=False)) def _parse_and_execute_csv(self, filepath): with open(filepath, 'r') as stream: # dialect = csv.Sniffer().sniff(stream.read(1024)) # check which type of formating the csv file likel has # stream.seek(0) reader = csv.DictReader(stream, dialect=csv.excel) # parse file for row in reader: # we wan't to remove spaces before and after the fields kwargs = {} for k, v in row.items(): kwargs[k.strip()] = v.strip() self._execute_script(**kwargs) # now we can execute the script def _print_example_csv(self): writer = csv.DictWriter(sys.stdout, fieldnames=self._params.keys()) writer.writeheader() writer.writerow(self._create_example_data_required(include_name=True)) writer.writerow(self._create_example_data_full(include_name=True)) def _execute_script(self, **kwargs): parsed_args = {} error = False for k, v in self._params.items(): try: if kwargs.get(k) not in [None, '']: parsed_args[k] = v.get('type', str)(kwargs[k]) elif v.get('required', False): raise ParserException("parameter expected: {}".format(k)) else: type = v.get('type', str) if type is bool: parsed_args[k] = type(v.get('default', False)) elif type is int: parsed_args[k] = type(v.get('default', 0)) elif type is float: parsed_args[k] = type(v.get('default', 0.0)) elif type is str: parsed_args[k] = type(v.get('default', '')) else: parsed_args[k] = type(v.get('default')) except (ValueError, ParserException) as e: error = True print("ERROR: {}".format(e)) print(" - generate {name}.kicad_mod".format(name=kwargs.get('name', ''))) if error: return self._footprint_function(parsed_args) ================================================ FILE: KicadModTree/Point.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, import warnings from KicadModTree.util.kicad_util import formatFloat from KicadModTree.Vector import * from math import sqrt class Point2D(Vector2D): def __init__(self, coordinates=None, y=None): Vector2D.__init__(self, coordinates, y) warnings.warn( "Point2D is deprecated, use Vector2D instead", DeprecationWarning ) class Point3D(Vector3D): def __init__(self, coordinates=None, y=None, z=None): Vector3D.__init__(self, coordinates, y, z) warnings.warn( "Point3D is deprecated, use Vector3D instead", DeprecationWarning ) class Point(Vector3D): def __init__(self, coordinates=None, y=None, z=None): Vector3D.__init__(self, coordinates, y, z) warnings.warn( "Point is deprecated, use Vector2D or Vector3D instead", DeprecationWarning ) ================================================ FILE: KicadModTree/PolygonPoints.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr import warnings from KicadModTree.Vector import Vector2D from KicadModTree.nodes.Node import Node class PolygonPoints(object): r"""Representation of multiple points for creating polygons :Keyword Arguments: * *nodes* (``list(Point)``) -- 2D points describing the "polygon" * *polygone* (``list(Point)``) -- alternative naming for the nodes parameter for backwards compatibility. * *x_mirror* (``[int, float](mirror offset)``) -- mirror x direction around offset "point" * *y_mirror* (``[int, float](mirror offset)``) -- mirror y direction around offset "point" :Example: >>> from KicadModTree import * >>> PolyPoint([(0, 0),(1, 0)]) >>> PolyPoint([{'x': 0, 'y':0}, {'x': 1, 'y':0}]) """ def __init__(self, **kwargs): self._initMirror(**kwargs) self._initNodes(**kwargs) def _initNodes(self, **kwargs): self.nodes = [] if 'nodes' in kwargs: for n in kwargs['nodes']: self.nodes.append(Vector2D(n)) if 'polygone' in kwargs: raise KeyError('Use of "nodes" and "polygone" parameter at the same time is not supported.') elif 'polygone' in kwargs: warnings.warn( "polygone argument is deprecated, use nodes instead", DeprecationWarning ) for n in kwargs['polygone']: self.nodes.append(Vector2D(n)) else: raise KeyError('Either "nodes" or "polygone" parameter is required for creating a PolyPoint instance.') for point in self.nodes: if self.mirror[0] is not None: point.x = 2 * self.mirror[0] - point.x if self.mirror[1] is not None: point.y = 2 * self.mirror[1] - point.y def _initMirror(self, **kwargs): self.mirror = [None, None] if 'x_mirror' in kwargs and type(kwargs['x_mirror']) in [float, int]: self.mirror[0] = kwargs['x_mirror'] if 'y_mirror' in kwargs and type(kwargs['y_mirror']) in [float, int]: self.mirror[1] = kwargs['y_mirror'] def calculateBoundingBox(self): min = max = self.getRealPosition(self.nodes[0]) for n in self.nodes: min.x = min([min.x, n.x]) min.y = min([min.y, n.y]) max.x = max([max.x, n.x]) max.y = max([max.y, n.y]) return Node.calculateBoundingBox({'min': min, 'max': max}) def findNearestPoints(self, other): r""" Find the nearest points for two polygons Find the two points for both polygons that are nearest to each other. :param other: the polygon points of the other polygon :return: a tuble with the indexes of the two points (pint in self, point in other) """ min_distance = self[0].distance_to(other[0]) pi = 0 pj = 0 for i in range(len(self)): for j in range(len(other)): d = self[i].distance_to(other[j]) if d < min_distance: pi = i pj = j min_distance = d return (pi, pj) def getPoints(self): r""" get the points contained within self :return: the array of points contained within this instance """ return self.nodes def cut(self, other): r""" Cut other polygon points from self As kicad has no native support for cuting one polygon from the other, the cut is done by connecting the nearest points of the two polygons with two lines on top of each other. This function assumes that the other polygon is fully within this one. It also assumes that connecting the two nearest points creates a valid polygon. (There are no geometry checks) :param other: the polygon points that are cut from this polygon """ warnings.warn( "No geometry checks are implement for cutting polygons.\n" "Make sure the second polygon is fully inside the main polygon\n" "Check resulting polygon carefully.", Warning ) idx_self, idx_other = self.findNearestPoints(other) self.nodes.insert(idx_self+1, self[idx_self]) for i in range(len(other)): self.nodes.insert(idx_self+1, other[(i+idx_other) % len(other)]) self.nodes.insert(idx_self+1, other[idx_other]) def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate points around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ for p in self.nodes: p.rotate(angle=angle, origin=origin, use_degrees=use_degrees) return self def translate(self, distance_vector): r""" Translate points :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ for p in self.nodes: p += distance_vector return self def __copy__(self): return PolygonPoints(nodes=self.nodes) def __iter__(self): for n in self.nodes: yield n def __getitem__(self, idx): return self.nodes[idx] def __len__(self): return len(self.nodes) ================================================ FILE: KicadModTree/Vector.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, from __future__ import division from builtins import round import warnings from KicadModTree.util.kicad_util import formatFloat from math import sqrt, sin, cos, hypot, atan2, degrees, radians class Vector2D(object): r"""Representation of a 2D Vector in space :Example: >>> from KicadModTree import * >>> Vector2D(0, 0) >>> Vector2D([0, 0]) >>> Vector2D((0, 0)) >>> Vector2D({'x': 0, 'y':0}) >>> Vector2D(Vector2D(0, 0)) """ def __init__(self, coordinates=None, y=None): # parse constructor if coordinates is None: coordinates = {} elif type(coordinates) in [int, float]: if y is not None: coordinates = [coordinates, y] else: raise TypeError('you have to give x and y coordinate') elif isinstance(coordinates, Vector2D): # convert Vector2D as well as Vector3D to dict coordinates = coordinates.to_dict() # parse vectors with format: Vector2D({'x':0, 'y':0}) if type(coordinates) is dict: self.x = float(coordinates.get('x', 0.)) self.y = float(coordinates.get('y', 0.)) return # parse vectors with format: Vector2D([0, 0]) or Vector2D((0, 0)) if type(coordinates) in [list, tuple]: if len(coordinates) == 2: self.x = float(coordinates[0]) self.y = float(coordinates[1]) return else: raise TypeError('invalid list size (2 elements expected)') raise TypeError('invalid parameters given') def round_to(self, base): r"""Round to a specific base (like it's required for a grid) :param base: base we want to round to :return: rounded point >>> from KicadModTree import * >>> Vector2D(0.1234, 0.5678).round_to(0.01) """ if base == 0 or base is None: return self.__copy__() return Vector2D([round(v / base) * base for v in self]) def distance_to(self, value): r"""Distance between this and another point :param value: the other point :return: distance between self and other point """ other = Vector2D.__arithmetic_parse(value) d = other - self return hypot(d.x, d.y) @staticmethod def __arithmetic_parse(value): if isinstance(value, Vector2D): return value elif type(value) in [int, float]: return Vector2D([value, value]) else: return Vector2D(value) def __eq__(self, other): if not isinstance(self, other.__class__): return False return self.x == other.x and self.y == other.y def __ne__(self, other): return not self.__eq__(other) def __add__(self, value): other = Vector2D.__arithmetic_parse(value) return Vector2D({'x': self.x + other.x, 'y': self.y + other.y}) def __iadd__(self, value): other = Vector2D.__arithmetic_parse(value) self.x += other.x self.y += other.y return self def __neg__(self): return Vector2D({'x': -self.x, 'y': -self.y}) def __sub__(self, value): other = Vector2D.__arithmetic_parse(value) return Vector2D({'x': self.x - other.x, 'y': self.y - other.y}) def __isub__(self, value): other = Vector2D.__arithmetic_parse(value) self.x -= other.x self.y -= other.y return self def __mul__(self, value): other = Vector2D.__arithmetic_parse(value) return Vector2D({'x': self.x * other.x, 'y': self.y * other.y}) def __div__(self, value): other = Vector2D.__arithmetic_parse(value) return Vector2D({'x': self.x / other.x, 'y': self.y / other.y}) def __truediv__(self, obj): return self.__div__(obj) def to_dict(self): return {'x': self.x, 'y': self.y} def render(self, formatcode): warnings.warn( "render is deprecated, read values directly instead", DeprecationWarning ) return formatcode.format(x=formatFloat(self.x), y=formatFloat(self.y)) def __repr__(self): return "Vector2D (x={x}, y={y})".format(**self.to_dict()) def __str__(self): return "(x={x}, y={y})".format(**self.to_dict()) def __getitem__(self, key): if key == 0 or key == 'x': return self.x if key == 1 or key == 'y': return self.y raise IndexError('Index {} is out of range'.format(key)) def __setitem__(self, key, item): if key == 0 or key == 'x': self.x = item elif key == 1 or key == 'y': self.y = item else: raise IndexError('Index {} is out of range'.format(key)) def __len__(self): return 2 def __iter__(self): yield self.x yield self.y def __copy__(self): return Vector2D(self.x, self.y) def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate vector around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ op = Vector2D(origin) if use_degrees: angle = radians(angle) temp = op.x + cos(angle) * (self.x - op.x) - sin(angle) * (self.y - op.y) self.y = op.y + sin(angle) * (self.x - op.x) + cos(angle) * (self.y - op.y) self.x = temp return self def to_polar(self, origin=(0, 0), use_degrees=True): r""" Get polar representation of the vector :params: * *origin* (``Vector2D``) origin point for polar conversion. default: (0, 0) * *use_degrees* (``boolean``) angle in degrees. default:True """ op = Vector2D(origin) diff = self - op radius = hypot(diff.x, diff.y) angle = atan2(diff.y, diff.x) if use_degrees: angle = degrees(angle) return (radius, angle) @staticmethod def from_polar(radius, angle, origin=(0, 0), use_degrees=True): r""" Generate a vector from its polar representation :params: * *radius* (``float``) lenght of the vector * *angle* (``float``) angle of the vector * *origin* (``Vector2D``) origin point for polar conversion. default: (0, 0) * *use_degrees* (``boolean``) angle in degrees. default:True """ if use_degrees: angle = radians(angle) x = radius * cos(angle) y = radius * sin(angle) return Vector2D({'x': x, 'y': y})+Vector2D(origin) def to_homogeneous(self): r""" Get homogeneous representation """ return Vector3D(self.x, self.y, 1) @staticmethod def from_homogeneous(source): r""" Recover 2d vector from its homogeneous representation :params: * *source* (``Vector3D``) 3d homogeneous representation """ return Vector2D(source.x/source.z, source.y/source.z) class Vector3D(Vector2D): r"""Representation of a 3D Vector in space :Example: >>> from KicadModTree import * >>> Vector3D(0, 0, 0) >>> Vector3D([0, 0, 0]) >>> Vector3D((0, 0, 0)) >>> Vector3D({'x': 0, 'y':0, 'z':0}) >>> Vector3D(Vector2D(0, 0)) >>> Vector3D(Vector3D(0, 0, 0)) """ def __init__(self, coordinates=None, y=None, z=None): # we don't need a super constructor here # parse constructor if coordinates is None: coordinates = {} elif type(coordinates) in [int, float]: if y is not None: if z is not None: coordinates = [coordinates, y, z] else: coordinates = [coordinates, y] else: raise TypeError('you have to give at least x and y coordinate') elif isinstance(coordinates, Vector2D): # convert Vector2D as well as Vector3D to dict coordinates = coordinates.to_dict() # parse vectors with format: Vector2D({'x':0, 'y':0}) if type(coordinates) is dict: self.x = float(coordinates.get('x', 0.)) self.y = float(coordinates.get('y', 0.)) self.z = float(coordinates.get('z', 0.)) return # parse vectors with format: Vector3D([0, 0]), Vector3D([0, 0, 0]) or Vector3D((0, 0)), Vector3D((0, 0, 0)) if type(coordinates) in [list, tuple]: if len(coordinates) >= 2: self.x = float(coordinates[0]) self.y = float(coordinates[1]) else: raise TypeError('invalid list size (to small)') if len(coordinates) == 3: self.z = float(coordinates[2]) else: self.z = 0. if len(coordinates) > 3: raise TypeError('invalid list size (to big)') else: raise TypeError('dict or list type required') def round_to(self, base): r"""Round to a specific base (like it's required for a grid) :param base: base we want to round to :return: rounded point >>> from KicadModTree import * >>> Vector3D(0.123, 0.456, 0.789).round_to(0.01) """ if base == 0 or base is None: return self.__copy__() return Vector3D([round(v / base) * base for v in self]) def cross_product(self, other): other = Vector3D.__arithmetic_parse(other) return Vector3D({ 'x': self.y*other.z - self.z*other.y, 'y': self.z*other.x - self.x*other.z, 'z': self.x*other.y - self.y*other.x}) def dot_product(self, other): other = Vector3D.__arithmetic_parse(other) return self.x*other.x + self.y*other.y + self.z*other.z @staticmethod def __arithmetic_parse(value): if isinstance(value, Vector3D): return value elif type(value) in [int, float]: return Vector3D([value, value, value]) else: return Vector3D(value) def __eq__(self, other): if not isinstance(self, other.__class__): return False return self.x == other.x and self.y == other.y and self.z == other.z def __ne__(self, other): return not self.__eq__(other) def __add__(self, value): other = Vector3D.__arithmetic_parse(value) return Vector3D({'x': self.x + other.x, 'y': self.y + other.y, 'z': self.z + other.z}) def __iadd__(self, value): other = Vector2D.__arithmetic_parse(value) self.x += other.x self.y += other.y self.z += other.z return self def __neg__(self): return Vector2D({'x': -self.x, 'y': -self.y, 'z': -self.z}) def __sub__(self, value): other = Vector3D.__arithmetic_parse(value) return Vector3D({'x': self.x - other.x, 'y': self.y - other.y, 'z': self.z - other.z}) def __isub__(self, value): other = Vector2D.__arithmetic_parse(value) self.x -= other.x self.y -= other.y self.z -= other.z return self def __mul__(self, value): other = Vector3D.__arithmetic_parse(value) return Vector3D({'x': self.x * other.x, 'y': self.y * other.y, 'z': self.z * other.z}) def __div__(self, value): other = Vector3D.__arithmetic_parse(value) return Vector3D({'x': self.x / other.x, 'y': self.y / other.y, 'z': self.z / other.z}) def __truediv__(self, obj): return self.__div__(obj) def to_dict(self): return {'x': self.x, 'y': self.y, 'z': self.z} def render(self, formatcode): warnings.warn( "render is deprecated, read values directly instead", DeprecationWarning ) return formatcode.format(x=formatFloat(self.x), y=formatFloat(self.y), z=formatFloat(self.z)) def __repr__(self): return "Vector3D (x={x}, y={y}, z={z})".format(**self.to_dict()) def __str__(self): return "(x={x}, y={y}, z={z})".format(**self.to_dict()) def __getitem__(self, key): if key == 0 or key == 'x': return self.x if key == 1 or key == 'y': return self.y if key == 2 or key == 'z': return self.z raise IndexError('Index {} is out of range'.format(key)) def __setitem__(self, key, item): if key == 0 or key == 'x': self.x = item elif key == 1 or key == 'y': self.y = item elif key == 2 or key == 'z': self.z = item else: raise IndexError('Index {} is out of range'.format(key)) def __len__(self): return 3 def __iter__(self): yield self.x yield self.y yield self.z def __copy__(self): return Vector3D(self.x, self.y, self.z) ================================================ FILE: KicadModTree/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.Point import * # backwards compatibility # all different types of nodes from KicadModTree.nodes import * # File Handlers from KicadModTree.KicadFileHandler import KicadFileHandler # Argparser from KicadModTree.ModArgparser import ModArgparser ================================================ FILE: KicadModTree/examples/__init__.py ================================================ ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' ================================================ FILE: KicadModTree/examples/argparse_example.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os sys.path.append(os.path.join(sys.path[0], "../..")) # enable package import from parent directory from KicadModTree import * # NOQA def example_footprint(args): print("now we can create a footprint using the following parameters:") print(args) if __name__ == '__main__': parser = ModArgparser(example_footprint) parser.add_parameter("name", type=str, required=True) # the root node of .yml files is parsed as name parser.add_parameter("datasheet", type=str, required=False) parser.add_parameter("courtyard", type=float, required=False, default=0.25) parser.add_parameter("diameter", type=float, required=True) parser.add_parameter("pad_length", type=float, required=True) parser.add_parameter("pad_width", type=float, required=True) parser.run() # now run our script which handles the whole part of parsing the files ================================================ FILE: KicadModTree/examples/padArrayWithOutline.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2017 by @SchrodingersGat # (C) 2017 by Thomas Pointhuber, import sys sys.path.append('../..') # enable package import from parent directory from KicadModTree import * # NOQA if __name__ == '__main__': footprint_name = "pad_array_footprint" # Init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("An example footprint") kicad_mod.setTags("example") # Set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, -3], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[1.5, 3], layer='F.Fab')) # Add model kicad_mod.append(Model(filename="example.3dshapes/example_footprint.wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # Create a pad array with a large horizontal spacing, and a smaller vertical spacing # centered at the origin pa = PadArray(pincount=10, spacing=[2.54, -0.2], center=[0, 0], initial=5, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[1, 2], layers=Pad.LAYERS_SMT) kicad_mod.append(pa) # Calculate the border of the pad array border = pa.calculateOutline() # Create a courtyard around the pad array kicad_mod.append(RectLine(start=border['min'], end=border['max'], layer='F.Fab', width=0.05, offset=0.5)) # Write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('example_footprint.kicad_mod') ================================================ FILE: KicadModTree/examples/params.csv ================================================ name, diameter, pad_length, pad_width 10x2x5,10,2,5 15x2x5,15,2,5 18x2x5,18,2,5 "Jsjdlfmlakefjsl , asldl",13,5,2.5 ================================================ FILE: KicadModTree/examples/params.yml ================================================ asdf: diameter: 10 pad_length: 3 pad_width: 7 ================================================ FILE: KicadModTree/examples/polygon.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os sys.path.append(os.path.join(sys.path[0], "../..")) # enable package import from parent directory from KicadModTree import * # NOQA if __name__ == '__main__': footprint_name = "example_footprint" # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, -3], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[1.5, 3], layer='F.Fab')) # create polygon kicad_mod.append(Polygon(nodes=[[-2, 0], [0, -2], [4, 0], [0, 2], [-2, 0], [0, -2], [4, 0], [0, 2]], layer='F.SilkS')) # print render tree print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('example_footprint.kicad_mod') ================================================ FILE: KicadModTree/examples/simpleFootprint.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os sys.path.append(os.path.join(sys.path[0], "../..")) # enable package import from parent directory from KicadModTree import * # NOQA if __name__ == '__main__': footprint_name = "example_footprint" # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, -3], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[1.5, 3], layer='F.Fab')) # create silkscreen kicad_mod.append(RectLine(start=[-2, -2], end=[5, 2], layer='F.SilkS')) # create courtyard kicad_mod.append(RectLine(start=[-2.25, -2.25], end=[5.25, 2.25], layer='F.CrtYd')) # create pads kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[3, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT)) # add model kicad_mod.append(Model(filename="example.3dshapes/example_footprint.wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # print render tree # print(kicad_mod.getRenderTree()) print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('example_footprint.kicad_mod') ================================================ FILE: KicadModTree/nodes/Footprint.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node ''' This is my new approach, using a render tree for footprint generation. ADVANTAGES: * simple point transformations * automatic calculation of courtjard,... * simple duplication of rendering structures ''' # define in which order the general "lisp" operators are arranged render_order = ['descr', 'tags', 'attr', 'solder_mask_margin', 'solder_paste_margin', 'solder_paste_ratio', 'fp_text', 'fp_circle', 'fp_line', 'pad', 'model'] # TODO: sort Text by type class Footprint(Node): ''' Root Node to generate KicadMod ''' def __init__(self, name): Node.__init__(self) self.name = name self.description = None self.tags = None self.attribute = None self.maskMargin = None self.pasteMargin = None self.pasteMarginRatio = None def setName(self, name): self.name = name def setDescription(self, description): self.description = description def setTags(self, tags): self.tags = tags def setAttribute(self, value): self.attribute = value def setMaskMargin(self, value): self.maskMargin = value def setPasteMargin(self, value): self.pasteMargin = value def setPasteMarginRatio(self, value): # paste_margin_ratio is unitless between 0 and 1 while GUI uses percentage assert abs(value) <= 1, "Solder paste margin must be between -1 and 1. {} is too large.".format(value) self.pasteMarginRatio = value ================================================ FILE: KicadModTree/nodes/Node.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from copy import copy, deepcopy from KicadModTree.Vector import * class MultipleParentsError(RuntimeError): def __init__(self, message): # Call the base class constructor with the parameters it needs super(MultipleParentsError, self).__init__(message) class RecursionDetectedError(RuntimeError): def __init__(self, message): # Call the base class constructor with the parameters it needs super(RecursionDetectedError, self).__init__(message) class Node(object): def __init__(self): self._parent = None self._childs = [] def append(self, node): ''' add node to child ''' if not isinstance(node, Node): raise TypeError('invalid object, has to be based on Node') if node._parent: raise MultipleParentsError('muliple parents are not allowed!') self._childs.append(node) node._parent = self def extend(self, nodes): ''' add list of nodes to child ''' new_nodes = [] for node in nodes: if not isinstance(node, Node): raise TypeError('invalid object, has to be based on Node') if node._parent or node in new_nodes: raise MultipleParentsError('muliple parents are not allowed!') new_nodes.append(node) # when all went smooth by now, we can set the parent nodes to ourself for node in new_nodes: node._parent = self self._childs.extend(new_nodes) def remove(self, node): ''' remove child from node ''' if not isinstance(node, Node): raise TypeError('invalid object, has to be based on Node') while node in self._childs: self._childs.remove(node) node._parent = None def insert(self, node): ''' moving all childs into the node, and using the node as new parent of those childs ''' if not isinstance(node, Node): raise TypeError('invalid object, has to be based on Node') for child in copy(self._childs): self.remove(child) node.append(child) self.append(node) def copy(self): copy = deepcopy(self) copy._parent = None return copy def serialize(self): nodes = [self] for child in self.getAllChilds(): nodes += child.serialize() return nodes def getNormalChilds(self): ''' Get all normal childs of this node ''' return self._childs def getVirtualChilds(self): ''' Get virtual childs of this node ''' return [] def getAllChilds(self): ''' Get virtual and normal childs of this node ''' return self.getNormalChilds() + self.getVirtualChilds() def getParent(self): ''' get Parent Node of this Node ''' return self._parent def getRootNode(self): ''' get Root Node of this Node ''' # TODO: recursion detection if not self.getParent(): return self return self.getParent().getRootNode() def getRealPosition(self, coordinate, rotation=None): ''' return position of point after applying all transformation and rotation operations ''' if not self._parent: if rotation is None: # TODO: most of the points are 2D Nodes return Vector3D(coordinate) else: return Vector3D(coordinate), rotation return self._parent.getRealPosition(coordinate, rotation) def calculateBoundingBox(self, outline=None): min_x, min_y = 0, 0 max_x, max_y = 0, 0 if outline: min_x = outline['min']['x'] min_y = outline['min']['y'] max_x = outline['max']['x'] max_y = outline['max']['y'] for child in self.getAllChilds(): child_outline = child.calculateBoundingBox() min_x = min([min_x, child_outline['min']['x']]) min_y = min([min_y, child_outline['min']['y']]) max_x = max([max_x, child_outline['max']['x']]) max_y = max([max_y, child_outline['max']['y']]) return {'min': Vector2D(min_x, min_y), 'max': Vector2D(max_x, max_y)} def _getRenderTreeText(self): ''' Text which is displayed when generating a render tree ''' return type(self).__name__ def _getRenderTreeSymbol(self): ''' Symbol which is displayed when generating a render tree ''' if self._parent is None: return "+" return "*" def getRenderTree(self, rendered_nodes=None): ''' print render tree ''' if rendered_nodes is None: rendered_nodes = set() if self in rendered_nodes: raise RecursionDetectedError('recursive definition of render tree!') rendered_nodes.add(self) tree_str = "{0} {1}".format(self._getRenderTreeSymbol(), self._getRenderTreeText()) for child in self.getNormalChilds(): tree_str += '\n ' tree_str += ' '.join(child.getRenderTree(rendered_nodes).splitlines(True)) return tree_str def getCompleteRenderTree(self, rendered_nodes=None): ''' print virtual render tree ''' if rendered_nodes is None: rendered_nodes = set() if self in rendered_nodes: raise RecursionDetectedError('recursive definition of render tree!') rendered_nodes.add(self) tree_str = "{0} {1}".format(self._getRenderTreeSymbol(), self._getRenderTreeText()) for child in self.getAllChilds(): tree_str += '\n ' tree_str += ' '.join(child.getCompleteRenderTree(rendered_nodes).splitlines(True)) return tree_str ================================================ FILE: KicadModTree/nodes/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, # generic node from .Node import Node, MultipleParentsError, RecursionDetectedError # root node from .Footprint import Footprint from .base import * from .specialized import * ================================================ FILE: KicadModTree/nodes/base/Arc.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node import math from KicadModTree.util.geometric_util import geometricArc, BaseNodeIntersection class Arc(Node, geometricArc): r"""Add an Arc to the render tree :param \**kwargs: See below :Keyword Arguments: * *geometry* (``geometricArc``) alternative to using geometric parameters * *center* (``Vector2D``) -- center of arc * *start* (``Vector2D``) -- start point of arc * *midpoint* (``Vector2D``) -- alternative to start point point is on arc and defines point of equal distance to both arc ends arcs of this form are given as midpoint, center plus angle * *end* (``Vector2D``) -- alternative to angle arcs of this form are given as start, end and center * *angle* (``float``) -- angle of arc * *layer* (``str``) -- layer on which the arc is drawn (default: 'F.SilkS') * *width* (``float``) -- width of the arc line (default: None, which means auto detection) :Example: >>> from KicadModTree import * >>> Arc(center=[0, 0], start=[-1, 0], angle=180, layer='F.SilkS') """ def __init__(self, **kwargs): Node.__init__(self) geometricArc.__init__(self, **kwargs) self.layer = kwargs.get('layer', 'F.SilkS') self.width = kwargs.get('width') def copyReplaceGeometry(self, geometry): return Arc(geometry=geometry, layer=self.layer, width=self.width) def copy(self): return Arc( center=self.center_pos, start=self.start_pos, angle=self.angle, layer=self.layer, width=self.width ) def cut(self, *other): r""" cut line with given other element :params: * *other* (``Line``, ``Circle``, ``Arc``) cut the element on any intersection with the given geometric element """ result = [] garcs = geometricArc.cut(self, *other) for g in garcs: result.append(self.copyReplaceGeometry(g)) return result def calculateBoundingBox(self): # TODO: finish implementation min_x = min(self.start_pos.x, self._calulateEndPos().x) min_y = min(self.start_pos.x, self._calulateEndPos().y) max_x = max(self.start_pos.x, self._calulateEndPos().x) max_y = max(self.start_pos.x, self._calulateEndPos().y) ''' for angle in range(4): float_angle = angle * math.pi/2. start_angle = _calculateStartAngle(self) end_angle = start_angle + math.radians(self.angle) # TODO: +- pi border if float_angle < start_angle: continue if float_angle > end_angle: continue print("TODO: add angle side: {1}".format(float_angle)) ''' return Node.calculateBoundingBox({'min': Vector2D((min_x, min_y)), 'max': Vector2D((max_x, max_y))}) def _getRenderTreeText(self): render_strings = ['fp_arc'] render_strings.append(self.center_pos.render('(center {x} {y})')) render_strings.append(self.start_pos.render('(start {x} {y})')) render_strings.append('(angle {angle})'.format(angle=self.angle)) render_strings.append('(layer {layer})'.format(layer=self.layer)) render_strings.append('(width {width})'.format(width=self.width)) render_text = Node._getRenderTreeText(self) render_text += ' ({})'.format(' '.join(render_strings)) return render_text ================================================ FILE: KicadModTree/nodes/base/Circle.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node from KicadModTree.util.geometric_util import geometricCircle, BaseNodeIntersection class Circle(Node, geometricCircle): r"""Add a Circle to the render tree :param \**kwargs: See below :Keyword Arguments: * *center* (``Vector2D``) -- center of the circle * *radius* (``float``) -- radius of the circle * *layer* (``str``) -- layer on which the circle is drawn (default: 'F.SilkS') * *width* (``float``) -- width of the circle line (default: None, which means auto detection) :Example: >>> from KicadModTree import * >>> Circle(center=[0, 0], radius=1.5, layer='F.SilkS') """ def __init__(self, **kwargs): Node.__init__(self) geometricCircle.__init__(self, Vector2D(kwargs['center']), float(kwargs['radius'])) self.layer = kwargs.get('layer', 'F.SilkS') self.width = kwargs.get('width') def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate circle around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.center_pos.rotate(angle=angle, origin=origin, use_degrees=use_degrees) return self def translate(self, distance_vector): r""" Translate circle :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.center_pos += distance_vector return self def cut(self, *other): raise NotImplemented("cut for circles not yet implemented") def getRadius(self): return self.radius def calculateBoundingBox(self): min_x = self.center_pos.x-self.radius min_y = self.center_pos.y-self.radius max_x = self.center_pos.x+self.radius max_y = self.center_pos.y+self.radius return Node.calculateBoundingBox({'min': ParseXY(min_x, min_y), 'max': ParseXY(max_x, max_y)}) def _getRenderTreeText(self): render_strings = ['fp_circle'] render_strings.append(self.center_pos.render('(center {x} {y})')) render_strings.append(self.end_pos.render('(end {x} {y})')) render_strings.append('(layer {layer})'.format(layer=self.layer)) render_strings.append('(width {width})'.format(width=self.width)) render_text = Node._getRenderTreeText(self) render_text += ' ({})'.format(' '.join(render_strings)) return render_text ================================================ FILE: KicadModTree/nodes/base/Line.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node from KicadModTree.util.geometric_util import geometricLine, BaseNodeIntersection class Line(Node, geometricLine): r"""Add a Line to the render tree :param \**kwargs: See below :Keyword Arguments: * *start* (``Vector2D``) -- start point of the line * *end* (``Vector2D``) -- end point of the line * *layer* (``str``) -- layer on which the line is drawn (default: 'F.SilkS') * *width* (``float``) -- width of the line (default: None, which means auto detection) :Example: >>> from KicadModTree import * >>> Line(start=[1, 0], end=[-1, 0], layer='F.SilkS') """ def __init__(self, **kwargs): Node.__init__(self) if 'geometry' in kwargs: geometry = kwargs['geometry'] geometricLine.__init__(self, geometry.start_pos, geometry.end_pos) else: geometricLine.__init__( self, start=Vector2D(kwargs['start']), end=Vector2D(kwargs['end']) ) self.layer = kwargs.get('layer', 'F.SilkS') self.width = kwargs.get('width') def copyReplaceGeometry(self, geometry): return Line( start=geometry.start_pos, end=geometry.end_pos, layer=self.layer, width=self.width ) def copy(self): return Line( start=self.start_pos, end=self.end_pos, layer=self.layer, width=self.width ) def cut(self, *other): r""" cut line with given other element :params: * *other* (``Line``, ``Circle``, ``Arc``) cut the element on any intersection with the given geometric element """ result = [] glines = geometricLine.cut(self, *other) for g in glines: result.append(self.copyReplaceGeometry(g)) return result def _getRenderTreeText(self): render_strings = ['fp_line'] render_strings.append(self.start_pos.render('(start {x} {y})')) render_strings.append(self.end_pos.render('(end {x} {y})')) render_strings.append('(layer {layer})'.format(layer=self.layer)) render_strings.append('(width {width})'.format(width=self.width)) render_text = Node._getRenderTreeText(self) render_text += ' ({})'.format(' '.join(render_strings)) return render_text def calculateBoundingBox(self): render_start_pos = self.getRealPosition(self.start_pos) render_end_pos = self.getRealPosition(self.end_pos) min_x = min([render_start_pos.x, render_end_pos.x]) min_y = min([render_start_pos.y, render_end_pos.y]) max_x = max([render_start_pos.x, render_end_pos.x]) max_y = max([render_start_pos.y, render_end_pos.y]) return Node.calculateBoundingBox({'min': Vector2D(min_x, min_y), 'max': Vector2D(max_x, max_y)}) ================================================ FILE: KicadModTree/nodes/base/Model.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node class Model(Node): r"""Add a 3D-Model to the render tree :param \**kwargs: See below :Keyword Arguments: * *filename* (``str``) -- name of the 3d-model file * *at* (``Vector3D``) -- position of the model (default: [0, 0, 0]) * *scale* (``Vector3D``) -- scale of the model (default: [1, 1, 1]) * *rotate* (``Vector3D``) -- rotation of the model (default: [0, 0, 0]) :Example: >>> from KicadModTree import * >>> Model(filename="example.3dshapes/example_footprint.wrl", ... at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0]) """ def __init__(self, **kwargs): Node.__init__(self) self.filename = kwargs['filename'] self.at = Vector3D(kwargs.get('at', [0, 0, 0])) self.scale = Vector3D(kwargs.get('scale', [1, 1, 1])) self.rotate = Vector3D(kwargs.get('rotate', [0, 0, 0])) def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_string = ['filename: {filename}'.format(filename=self.filename), 'at: {at}'.format(at=self.at.render('(xyz {x} {y} {z})')), 'scale: {scale}'.format(scale=self.scale.render('(xyz {x} {y} {z})')), 'rotate: {rotate}'.format(rotate=self.rotate.render('(xyz {x} {y} {z})'))] render_text += " [{}]".format(", ".join(render_string)) return render_text ================================================ FILE: KicadModTree/nodes/base/Pad.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr from KicadModTree.util.paramUtil import * from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node from KicadModTree.util.kicad_util import lispString from KicadModTree.nodes.base.Arc import Arc from KicadModTree.nodes.base.Circle import Circle from KicadModTree.nodes.base.Line import Line from KicadModTree.nodes.base.Polygon import Polygon class RoundRadiusHandler(object): r"""Handles round radius setting of a pad :param \**kwargs: See below :Keyword Arguments: * *radius_ratio* (``float [0 <= r <= 0.5]``) -- The radius ratio of the rounded rectangle. (default set by default_radius_ratio) * *maximum_radius* (``float``) -- The maximum radius for the rounded rectangle. If the radius produced by the radius_ratio parameter for the pad would exceed the maximum radius, the ratio is reduced to limit the radius. (This is useful for IPC-7351C compliance as it suggests 25% ratio with limit 0.25mm) * *round_radius_exact* (``float``) -- Set an exact round radius for a pad. * *default_radius_ratio* (``float [0 <= r <= 0.5]``) -- This parameter allows to set the default radius ratio (backwards compatibility option for chamfered pads) """ def __init__(self, **kwargs): default_radius_ratio = getOptionalNumberTypeParam( kwargs, 'default_radius_ratio', default_value=0.25, low_limit=0, high_limit=0.5) self.radius_ratio = getOptionalNumberTypeParam( kwargs, 'radius_ratio', default_value=default_radius_ratio, low_limit=0, high_limit=0.5) self.maximum_radius = getOptionalNumberTypeParam(kwargs, 'maximum_radius') self.round_radius_exact = getOptionalNumberTypeParam(kwargs, 'round_radius_exact') self.kicad4_compatible = kwargs.get('kicad4_compatible', False) def getRadiusRatio(self, shortest_sidelength): r"""get the resulting round radius ratio :param shortest_sidelength: shortest sidelength of a pad :return: the resulting round radius ratio to be used for the pad """ if self.kicad4_compatible: return 0 if self.round_radius_exact is not None: if self.round_radius_exact > shortest_sidelength/2: raise ValueError( "requested round radius of {} is too large for pad size of {}" .format(self.round_radius_exact, pad_size) ) if self.maximum_radius is not None: return min(self.round_radius_exact, self.maximum_radius)/shortest_sidelength else: return self.round_radius_exact/shortest_sidelength if self.maximum_radius is not None: if self.radius_ratio*shortest_sidelength > self.maximum_radius: return self.maximum_radius/shortest_sidelength return self.radius_ratio def getRoundRadius(self, shortest_sidelength): r"""get the resulting round radius :param shortest_sidelength: shortest sidelength of a pad :return: the resulting round radius to be used for the pad """ return self.getRadiusRatio(shortest_sidelength)*shortest_sidelength def roundingRequested(self): r"""Check if the pad has a rounded corner :return: True if rounded corners are required """ if self.kicad4_compatible: return False if self.maximum_radius == 0: return False if self.round_radius_exact == 0: return False if self.radius_ratio == 0: return False return True def limitMaxRadius(self, limit): r"""Set a new maximum limit :param limit: the new limit. """ if not self.roundingRequested(): return if self.maximum_radius is not None: self.maximum_radius = min(self.maximum_radius, limit) else: self.maximum_radius = limit def __str__(self): return "ratio {}, max {}, exact {}, v4 compatible {}".format( self.radius_ratio, self.maximum_radius, self.round_radius_exact, self.kicad4_compatible ) class Pad(Node): r"""Add a Pad to the render tree :param \**kwargs: See below :Keyword Arguments: * *number* (``int``, ``str``) -- number/name of the pad (default: \"\") * *type* (``Pad.TYPE_THT``, ``Pad.TYPE_SMT``, ``Pad.TYPE_CONNECT``, ``Pad.TYPE_NPTH``) -- type of the pad * *shape* (``Pad.SHAPE_CIRCLE``, ``Pad.SHAPE_OVAL``, ``Pad.SHAPE_RECT``, ``SHAPE_ROUNDRECT``, ``Pad.SHAPE_TRAPEZE``, ``SHAPE_CUSTOM``) -- shape of the pad * *layers* (``Pad.LAYERS_SMT``, ``Pad.LAYERS_THT``, ``Pad.LAYERS_NPTH``) -- layers on which are used for the pad * *at* (``Vector2D``) -- center position of the pad * *rotation* (``float``) -- rotation of the pad * *size* (``float``, ``Vector2D``) -- size of the pad * *offset* (``Vector2D``) -- offset of the pad * *drill* (``float``, ``Vector2D``) -- drill-size of the pad * *radius_ratio* (``float``) -- The radius ratio of the rounded rectangle. Ignored for every shape except round rect. * *maximum_radius* (``float``) -- The maximum radius for the rounded rectangle. If the radius produced by the radius_ratio parameter for the pad would exceed the maximum radius, the ratio is reduced to limit the radius. (This is useful for IPC-7351C compliance as it suggests 25% ratio with limit 0.25mm) Ignored for every shape except round rect. * *round_radius_exact* (``float``) -- Set an exact round radius for a pad. Ignored for every shape except round rect * *round_radius_handler* (``RoundRadiusHandler``) -- An instance of the RoundRadiusHandler class If this is given then all other round radius specifiers are ignored Ignored for every shape except round rect * *solder_paste_margin_ratio* (``float``) -- solder paste margin ratio of the pad (default: 0) * *solder_paste_margin* (``float``) -- solder paste margin of the pad (default: 0) * *solder_mask_margin* (``float``) -- solder mask margin of the pad (default: 0) * *x_mirror* (``[int, float](mirror offset)``) -- mirror x direction around offset "point" * *y_mirror* (``[int, float](mirror offset)``) -- mirror y direction around offset "point" :Example: >>> from KicadModTree import * >>> Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, ... at=[0, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT) """ TYPE_THT = 'thru_hole' TYPE_SMT = 'smd' TYPE_CONNECT = 'connect' TYPE_NPTH = 'np_thru_hole' _TYPES = [TYPE_THT, TYPE_SMT, TYPE_CONNECT, TYPE_NPTH] SHAPE_CIRCLE = 'circle' SHAPE_OVAL = 'oval' SHAPE_RECT = 'rect' SHAPE_ROUNDRECT = 'roundrect' SHAPE_TRAPEZE = 'trapezoid' SHAPE_CUSTOM = 'custom' _SHAPES = [SHAPE_CIRCLE, SHAPE_OVAL, SHAPE_RECT, SHAPE_ROUNDRECT, SHAPE_TRAPEZE, SHAPE_CUSTOM] LAYERS_SMT = ['F.Cu', 'F.Mask', 'F.Paste'] LAYERS_THT = ['*.Cu', '*.Mask'] LAYERS_NPTH = ['*.Cu', '*.Mask'] ANCHOR_CIRCLE = 'circle' ANCHOR_RECT = 'rect' _ANCHOR_SHAPE = [ANCHOR_CIRCLE, ANCHOR_RECT] SHAPE_IN_ZONE_CONVEX = 'convexhull' SHAPE_IN_ZONE_OUTLINE = 'outline' _SHAPE_IN_ZONE = [SHAPE_IN_ZONE_CONVEX, SHAPE_IN_ZONE_OUTLINE] def __init__(self, **kwargs): Node.__init__(self) self.radius_ratio = 0 self._initNumber(**kwargs) self._initType(**kwargs) self._initShape(**kwargs) self._initPosition(**kwargs) self._initSize(**kwargs) self._initOffset(**kwargs) self._initDrill(**kwargs) # requires pad type and offset self._initSolderPasteMargin(**kwargs) self._initSolderPasteMarginRatio(**kwargs) self._initSolderMaskMargin(**kwargs) self._initLayers(**kwargs) self._initMirror(**kwargs) if self.shape == self.SHAPE_OVAL and self.size[0] == self.size[1]: self.shape = self.SHAPE_CIRCLE if self.shape == Pad.SHAPE_OVAL or self.shape == Pad.SHAPE_CIRCLE: self.radius_ratio = 0.5 if self.shape == Pad.SHAPE_ROUNDRECT: self._initRadiusRatio(**kwargs) if self.shape == Pad.SHAPE_CUSTOM: self._initAnchorShape(**kwargs) self._initShapeInZone(**kwargs) self.primitives = [] if 'primitives' not in kwargs: raise KeyError('primitives must be declared for custom pads') for p in kwargs['primitives']: self.addPrimitive(p) def _initMirror(self, **kwargs): self.mirror = [None, None] if 'x_mirror' in kwargs and type(kwargs['x_mirror']) in [float, int]: self.mirror[0] = kwargs['x_mirror'] if 'y_mirror' in kwargs and type(kwargs['y_mirror']) in [float, int]: self.mirror[1] = kwargs['y_mirror'] if self.mirror[0] is not None: self.at.x = 2 * self.mirror[0] - self.at.x self.offset.x *= -1 if self.mirror[1] is not None: self.at.y = 2 * self.mirror[1] - self.at.y self.offset.y *= -1 def _initNumber(self, **kwargs): self.number = kwargs.get('number', "") # default to an un-numbered pad def _initType(self, **kwargs): if not kwargs.get('type'): raise KeyError('type not declared (like "type=Pad.TYPE_THT")') self.type = kwargs.get('type') if self.type not in Pad._TYPES: raise ValueError('{type} is an invalid type for pads'.format(type=self.type)) def _initShape(self, **kwargs): if not kwargs.get('shape'): raise KeyError('shape not declared (like "shape=Pad.SHAPE_CIRCLE")') self.shape = kwargs.get('shape') if self.shape not in Pad._SHAPES: raise ValueError('{shape} is an invalid shape for pads'.format(shape=self.shape)) def _initPosition(self, **kwargs): if not kwargs.get('at'): raise KeyError('center position not declared (like "at=[0,0]")') self.at = Vector2D(kwargs.get('at')) self.rotation = kwargs.get('rotation', 0) def _initSize(self, **kwargs): if not kwargs.get('size'): raise KeyError('pad size not declared (like "size=[1,1]")') self.size = toVectorUseCopyIfNumber(kwargs.get('size'), low_limit=0) def _initOffset(self, **kwargs): self.offset = Vector2D(kwargs.get('offset', [0, 0])) def _initDrill(self, **kwargs): if self.type in [Pad.TYPE_THT, Pad.TYPE_NPTH]: if not kwargs.get('drill'): raise KeyError('drill size required (like "drill=1")') self.drill = toVectorUseCopyIfNumber(kwargs.get('drill'), low_limit=0) else: self.drill = None if kwargs.get('drill'): pass # TODO: throw warning because drill is not supported def _initSolderPasteMarginRatio(self, **kwargs): self.solder_paste_margin_ratio = kwargs.get('solder_paste_margin_ratio', 0) def _initSolderPasteMargin(self, **kwargs): self.solder_paste_margin = kwargs.get('solder_paste_margin', 0) def _initSolderMaskMargin(self, **kwargs): self.solder_mask_margin = kwargs.get('solder_mask_margin', 0) def _initLayers(self, **kwargs): if not kwargs.get('layers'): raise KeyError('layers not declared (like "layers=[\'*.Cu\', \'*.Mask\', \'F.SilkS\']")') self.layers = kwargs.get('layers') def _initRadiusRatio(self, **kwargs): if('round_radius_handler' in kwargs): self.round_radius_handler = kwargs['round_radius_handler'] else: self.round_radius_handler = RoundRadiusHandler(**kwargs) self.radius_ratio = self.round_radius_handler.getRadiusRatio(min(self.size)) if self.radius_ratio == 0: self.shape = Pad.SHAPE_RECT def _initAnchorShape(self, **kwargs): self.anchor_shape = kwargs.get('anchor_shape', Pad.ANCHOR_CIRCLE) if self.anchor_shape not in Pad._ANCHOR_SHAPE: raise ValueError('{shape} is an illegal anchor shape'.format(shape=self.anchor_shape)) def _initShapeInZone(self, **kwargs): self.shape_in_zone = kwargs.get('shape_in_zone', Pad.SHAPE_IN_ZONE_OUTLINE) if self.shape_in_zone not in Pad._SHAPE_IN_ZONE: raise ValueError('{shape} is an illegal specifier for the shape in zone option' .format(shape=self.shape_in_zone)) def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate pad around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.at.rotate(angle=angle, origin=origin, use_degrees=use_degrees) a = angle if use_degrees else math.degrees(angle) # subtraction because kicad text field rotation is the wrong way round self.rotation -= a return self def translate(self, distance_vector): r""" Translate pad :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.at += distance_vector return self # calculate the outline of a pad def calculateBoundingBox(self): return Node.calculateBoundingBox(self) def _getRenderTreeText(self): render_strings = ['pad'] render_strings.append(lispString(self.number)) render_strings.append(lispString(self.type)) render_strings.append(lispString(self.shape)) render_strings.append(self.at.render('(at {x} {y})')) render_strings.append(self.size.render('(size {x} {y})')) render_strings.append('(drill {})'.format(self.drill)) render_strings.append('(layers {})'.format(' '.join(self.layers))) render_text = Node._getRenderTreeText(self) render_text += '({})'.format(' '.join(render_strings)) return render_text def addPrimitive(self, p): r""" add a primitve to a custom pad :param p: the primitive to add """ self.primitives.append(p) def getRoundRadius(self): if self.shape == Pad.SHAPE_CUSTOM: r_max = 0 for p in self.primitives: r = p.width/2 if r > r_max: r_max = r return r_max return self.round_radius_handler.getRoundRadius(min(self.size)) ================================================ FILE: KicadModTree/nodes/base/Polygon.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2018 by Thomas Pointhuber, from KicadModTree.PolygonPoints import * from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node class Polygon(Node): r"""Add a Polygon to the render tree :param \**kwargs: See below :Keyword Arguments: * *polygon* (``list(Point)``) -- outer nodes of the polygon * *layer* (``str``) -- layer on which the line is drawn (default: 'F.SilkS') * *width* (``float``) -- width of the line (default: None, which means auto detection) * *x_mirror* (``[int, float](mirror offset)``) -- mirror x direction around offset "point" * *y_mirror* (``[int, float](mirror offset)``) -- mirror y direction around offset "point" :Example: >>> from KicadModTree import * >>> Polygon(nodes=[[-2, 0], [0, -2], [4, 0], [0, 2]], layer='F.SilkS') """ def __init__(self, **kwargs): Node.__init__(self) self.nodes = PolygonPoints(**kwargs) self.layer = kwargs.get('layer', 'F.SilkS') self.width = kwargs.get('width') def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate polygon around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.nodes.rotate(angle=angle, origin=origin, use_degrees=use_degrees) return self def translate(self, distance_vector): r""" Translate polygon :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.nodes.translate(distance_vector) return self def calculateBoundingBox(self): return nodes.calculateBoundingBox() def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_text += " [nodes: [" node_strings = [] for n in self.nodes: node_strings.append("[x: {x}, y: {y}]".format(x=n.x, y=n.y)) if len(node_strings) <= 6: render_text += ", ".join(node_strings) else: # display only a few nodes of the beginning and the end of the polygone line render_text += ", ".join(node_strings[:3]) render_text += ",... , " render_text += ", ".join(node_strings[-3:]) render_text += "]" return render_text def cut(self, other): r""" Cut other polygon from this polygon More details see PolygonPoints.cut docstring. :param other: the other polygon """ self.nodes.cut(other.nodes) ================================================ FILE: KicadModTree/nodes/base/Text.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node class Text(Node): r"""Add a Line to the render tree :param \**kwargs: See below :Keyword Arguments: * *type* (``str``) -- type of text * *text* (``str``) -- text which is been visualized * *at* (``Vector2D``) -- position of text * *rotation* (``float``) -- rotation of text (default: 0) * *mirror* (``bool``) -- mirror text (default: False) * *layer* (``str``) -- layer on which the text is drawn (default: 'F.SilkS') * *size* (``Vector2D``) -- size of the text (default: [1, 1]) * *thickness* (``float``) -- thickness of the text (default: 0.15) * *hide* (``bool``) -- hide text (default: False) :Example: >>> from KicadModTree import * >>> Text(type='reference', text='REF**', at=[0, -3], layer='F.SilkS') >>> Text(type='value', text="footprint name", at=[0, 3], layer='F.Fab') >>> Text(type='user', text='test', at=[0, 0], layer='Cmts.User') """ TYPE_REFERENCE = 'reference' TYPE_VALUE = 'value' TYPE_USER = 'user' _TYPES = [TYPE_REFERENCE, TYPE_VALUE, TYPE_USER] def __init__(self, **kwargs): Node.__init__(self) self._initType(**kwargs) self.text = kwargs['text'] self.at = Vector2D(kwargs['at']) self.rotation = kwargs.get('rotation', 0) self.mirror = kwargs.get('mirror', False) self.layer = kwargs.get('layer', 'F.SilkS') self.size = Vector2D(kwargs.get('size', [1, 1])) self.thickness = kwargs.get('thickness', 0.15) self.hide = kwargs.get('hide', False) def _initType(self, **kwargs): self.type = kwargs['type'] if self.type not in Text._TYPES: raise ValueError('Illegal type selected for text field.') def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate text around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.at.rotate(angle=angle, origin=origin, use_degrees=use_degrees) a = angle if use_degrees else math.degrees(angle) # subtraction because kicad text field rotation is the wrong way round self.rotation -= a return self def translate(self, distance_vector): r""" Translate text :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.at += distance_vector return self def calculateBoundingBox(self): width = len(self.text)*self.size['x'] height = self.size['y'] min_x = self.at['x']-width/2. min_y = self.at['y']-height/2. max_x = self.at['x']+width/2. max_y = self.at['y']+height/2. return Node.calculateBoundingBox({'min': Vector2D(min_x, min_y), 'max': Vector2D(max_x, max_y)}) def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_string = ['type: "{}"'.format(self.type), 'text: "{}"'.format(self.text), 'at: {}'.format(self.at.render('(at {x} {y})')), 'layer: {}'.format(self.layer), 'size: {}'.format(self.size.render('(size {x} {y})')), 'thickness: {}'.format(self.thickness)] render_text += " [{}]".format(", ".join(render_string)) return render_text ================================================ FILE: KicadModTree/nodes/base/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, from .Arc import Arc from .Circle import Circle from .Line import Line from .Model import Model from .Pad import Pad from .Polygon import Polygon from .Text import Text ================================================ FILE: KicadModTree/nodes/specialized/ChamferedPad.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr from __future__ import division from copy import copy from KicadModTree.util.paramUtil import * from KicadModTree.Vector import * from KicadModTree.nodes.base.Polygon import * from KicadModTree.nodes.base.Pad import Pad, RoundRadiusHandler from math import sqrt class CornerSelection(): r"""Class for handling chamfer selection :param chamfer_select: * A list of bools do directly set the corners (top left, top right, bottom right, bottom left) * A dict with keys (constands see below) * The integer 1 means all corners * The integer 0 means no corners :constants: * CornerSelection.TOP_LEFT * CornerSelection.TOP_RIGHT * CornerSelection.BOTTOM_RIGHT * CornerSelection.BOTTOM_LEFT """ TOP_LEFT = 'tl' TOP_RIGHT = 'tr' BOTTOM_RIGHT = 'br' BOTTOM_LEFT = 'bl' def __init__(self, chamfer_select): self.top_left = False self.top_right = False self.bottom_right = False self.bottom_left = False if chamfer_select == 1: self.selectAll() return if chamfer_select == 0: return if type(chamfer_select) is dict: for key in chamfer_select: self[key] = bool(chamfer_select[key]) else: for i, value in enumerate(chamfer_select): self[i] = bool(value) def selectAll(self): for i in range(len(self)): self[i] = True def clearAll(self): for i in range(len(self)): self[i] = False def setLeft(self, value=1): self.top_left = bool(value) self.bottom_left = bool(value) def setTop(self, value=1): self.top_left = bool(value) self.top_right = bool(value) def setRight(self, value=1): self.top_right = bool(value) self.bottom_right = bool(value) def setBottom(self, value=1): self.bottom_left = bool(value) self.bottom_right = bool(value) def isAnySelected(self): for v in self: if v: return True return False def rotateCW(self): top_left_old = self.top_left self.top_left = self.bottom_left self.bottom_left = self.bottom_right self.bottom_right = self.top_right self.top_right = top_left_old return self def rotateCCW(self): top_left_old = self.top_left self.top_left = self.top_right self.top_right = self.bottom_right self.bottom_right = self.bottom_left self.bottom_left = top_left_old return self def __or__(self, other): return CornerSelection([s or o for s, o in zip(self, other)]) def __ior__(self, other): for i in range(len(self)): self[i] |= other[i] return self def __and__(self, other): return CornerSelection([s and o for s, o in zip(self, other)]) def __iand__(self, other): for i in range(len(self)): self[i] &= other[i] return self def __len__(self): return 4 def __iter__(self): yield self.top_left yield self.top_right yield self.bottom_right yield self.bottom_left def __getitem__(self, item): if item in [0, CornerSelection.TOP_LEFT]: return self.top_left if item in [1, CornerSelection.TOP_RIGHT]: return self.top_right if item in [2, CornerSelection.BOTTOM_RIGHT]: return self.bottom_right if item in [3, CornerSelection.BOTTOM_LEFT]: return self.bottom_left raise IndexError('Index {} is out of range'.format(item)) def __setitem__(self, item, value): if item in [0, CornerSelection.TOP_LEFT]: self.top_left = bool(value) elif item in [1, CornerSelection.TOP_RIGHT]: self.top_right = bool(value) elif item in [2, CornerSelection.BOTTOM_RIGHT]: self.bottom_right = bool(value) elif item in [3, CornerSelection.BOTTOM_LEFT]: self.bottom_left = bool(value) else: raise IndexError('Index {} is out of range'.format(item)) def to_dict(self): return { CornerSelection.TOP_LEFT: self.top_left, CornerSelection.TOP_RIGHT: self.top_right, CornerSelection.BOTTOM_RIGHT: self.bottom_right, CornerSelection.BOTTOM_LEFT: self.bottom_left } def __str__(self): return str(self.to_dict()) class ChamferedPad(Node): r"""Add a ChamferedPad to the render tree :param \**kwargs: See below :Keyword Arguments: * *number* (``int``, ``str``) -- number/name of the pad (default: \"\") * *type* (``Pad.TYPE_THT``, ``Pad.TYPE_SMT``, ``Pad.TYPE_CONNECT``, ``Pad.TYPE_NPTH``) -- type of the pad * *at* (``Vector2D``) -- center position of the pad * *rotation* (``float``) -- rotation of the pad * *size* (``float``, ``Vector2D``) -- size of the pad * *offset* (``Vector2D``) -- offset of the pad * *drill* (``float``, ``Vector2D``) -- drill-size of the pad * *solder_paste_margin_ratio* (``float``) -- solder paste margin ratio of the pad (default: 0) * *solder_paste_margin* (``float``) -- solder paste margin of the pad (default: 0) * *solder_mask_margin* (``float``) -- solder mask margin of the pad (default: 0) * *layers* (``Pad.LAYERS_SMT``, ``Pad.LAYERS_THT``, ``Pad.LAYERS_NPTH``) -- layers on which are used for the pad * *corner_selection* (``CornerSelection``) -- Select which corner(s) to chamfer. (top left, top right, bottom right, bottom left) * *chamfer_size* (``float``, ``Vector2D``) -- Size of the chamfer. * *x_mirror* (``[int, float](mirror offset)``) -- mirror x direction around offset "point" * *y_mirror* (``[int, float](mirror offset)``) -- mirror y direction around offset "point" * *radius_ratio* (``float``) -- The radius ratio of the rounded rectangle. (default 0 for backwards compatibility) * *maximum_radius* (``float``) -- The maximum radius for the rounded rectangle. If the radius produced by the radius_ratio parameter for the pad would exceed the maximum radius, the ratio is reduced to limit the radius. (This is useful for IPC-7351C compliance as it suggests 25% ratio with limit 0.25mm) * *round_radius_exact* (``float``) -- Set an exact round radius for a pad. * *round_radius_handler* (``RoundRadiusHandler``) -- An instance of the RoundRadiusHandler class If this is given then all other round radius specifiers are ignored """ def __init__(self, **kwargs): Node.__init__(self) self._initPosition(**kwargs) self._initSize(**kwargs) self._initMirror(**kwargs) self._initPadSettings(**kwargs) self.pad = self._generatePad() def _initSize(self, **kwargs): if not kwargs.get('size'): raise KeyError('pad size not declared (like "size=[1,1]")') self.size = toVectorUseCopyIfNumber(kwargs.get('size'), low_limit=0) def _initPosition(self, **kwargs): if 'at' not in kwargs: raise KeyError('center position not declared (like "at=[0,0]")') self.at = Vector2D(kwargs.get('at')) def _initMirror(self, **kwargs): self.mirror = {} if 'x_mirror' in kwargs and type(kwargs['x_mirror']) in [float, int]: self.mirror['x_mirror'] = kwargs['x_mirror'] if 'y_mirror' in kwargs and type(kwargs['y_mirror']) in [float, int]: self.mirror['y_mirror'] = kwargs['y_mirror'] def _initPadSettings(self, **kwargs): if 'corner_selection' not in kwargs: raise KeyError('corner selection is required for chamfered pads (like "corner_selection=[1,0,0,0]")') self.corner_selection = CornerSelection(kwargs.get('corner_selection')) if 'chamfer_size' not in kwargs: self.chamfer_size = Vector2D(0, 0) else: self.chamfer_size = toVectorUseCopyIfNumber( kwargs.get('chamfer_size'), low_limit=0, must_be_larger=False) if('round_radius_handler' in kwargs): self.round_radius_handler = kwargs['round_radius_handler'] else: # default radius ration 0 for backwards compatibility self.round_radius_handler = RoundRadiusHandler(default_radius_ratio=0, **kwargs) self.padargs = copy(kwargs) self.padargs.pop('size', None) self.padargs.pop('shape', None) self.padargs.pop('at', None) self.padargs.pop('round_radius_handler', None) def _generatePad(self): if self.chamfer_size[0] >= self.size[0] or self.chamfer_size[1] >= self.size[1]: raise ValueError('Chamfer size ({}) too large for given pad size ({})'.format(self.chamfer_size, self.size)) is_chamfered = False if self.corner_selection.isAnySelected() and self.chamfer_size[0] > 0 and self.chamfer_size[1] > 0: is_chamfered = True radius = self.round_radius_handler.getRoundRadius(min(self.size)) if is_chamfered: outside = Vector2D(self.size.x/2, self.size.y/2) inside = [Vector2D(outside.x, outside.y-self.chamfer_size.y), Vector2D(outside.x-self.chamfer_size.x, outside.y) ] polygon_width = 0 if self.round_radius_handler.roundingRequested(): if self.chamfer_size[0] != self.chamfer_size[1]: raise NotImplementedError( 'Rounded chamfered pads are only supported for 45 degree chamfers.' ' Chamfer {}'.format(self.chamfer_size) ) # We prefer the use of rounded rectangle over chamfered pads. r_chamfer = self.chamfer_size[0] + sqrt(2)*self.chamfer_size[0]/2 if radius >= r_chamfer: is_chamfered = False elif radius > 0: shortest_sidlength = min(min(self.size-self.chamfer_size), self.chamfer_size[0]*sqrt(2)) if radius > shortest_sidlength/2: radius = shortest_sidlength/2 polygon_width = radius*2 outside -= radius inside[0].y -= radius*(2/sqrt(2)-1) inside[0].x -= radius inside[1].x -= radius*(2/sqrt(2)-1) inside[1].y -= radius if is_chamfered: points = [] corner_vectors = [ Vector2D(-1, -1), Vector2D(1, -1), Vector2D(1, 1), Vector2D(-1, 1) ] for i in range(4): if self.corner_selection[i]: points.append(corner_vectors[i]*inside[i % 2]) points.append(corner_vectors[i]*inside[(i+1) % 2]) else: points.append(corner_vectors[i]*outside) primitives = [Polygon(nodes=points, width=polygon_width, **self.mirror)] # TODO make size calculation more resilient size = min(self.size.x, self.size.y)-max(self.chamfer_size[0], self.chamfer_size[1])/sqrt(2) if size <= 0: raise ValueError('Anchor pad size calculation failed.' 'Chamfer size ({}) to large for given pad size ({})' .format(self.size, self.chamfer_size)) return Pad(primitives=primitives, at=self.at, shape=Pad.SHAPE_CUSTOM, size=size, **self.padargs) else: return Pad( at=self.at, shape=Pad.SHAPE_ROUNDRECT, size=self.size, round_radius_handler=self.round_radius_handler, **self.padargs ) def chamferAvoidCircle(self, center, diameter, clearance=0): r""" set the chamfer such that the pad avoids a cricle located at near corner. :param center: (``Vector2D``) -- The center of the circle ot avoid :param diameter: (``float``, ``Vector2D``) -- The diameter of the circle. If Vector2D given only x direction is used. :param clearance: (``float``) -- Additional clearance around circle. default:0 """ relative_center = Vector2D(center) - self.at # pad and circle are symetric so we do not care which corner the # reference circle is located at. # -> move it to bottom right to get only positive relative coordinates. relative_center = Vector2D([abs(v) for v in relative_center]) d = diameter if type(diameter) in [float, int] else diameter.x # Where should the chamfer be if the center of the reference circle # would be in line with the pad edges # (meaning exactly at the bottome right corner) reference_point = relative_center - sqrt(2)*(clearance+d/2) self.chamfer_size = self.size/2 - reference_point # compensate for reference circles not placed exactly at the corner edge_to_center = relative_center - self.size/2 self.chamfer_size -= [edge_to_center.y, edge_to_center.x] self.chamfer_size = Vector2D([x if x > 0 else 0 for x in self.chamfer_size]) self.pad = self._generatePad() return self.chamfer_size def getVirtualChilds(self): return [self.pad] def getRoundRadius(self): return self.pad.getRoundRadius() ================================================ FILE: KicadModTree/nodes/specialized/ChamferedPadGrid.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr from __future__ import division from KicadModTree.util.paramUtil import * from KicadModTree.Vector import * from KicadModTree.nodes.base.Polygon import * from KicadModTree.nodes.specialized.ChamferedPad import * class ChamferSelPadGrid(CornerSelection): r"""Class for handling chamfer selection :param chamfer_select: * A list of bools do directly set the corners (top left, top right, bottom right, bottom left) * A dict with keys (Constands see below) * The integer 1 means all corners and edges * The integer 0 means no corners, no edges :constants: * ChamferSelPadGrid.TOP_EDGE * ChamferSelPadGrid.RIGHT_EDGE * ChamferSelPadGrid.BOTTOM_EDGE * ChamferSelPadGrid.LEFT_EDGE * Plus all constands inherited from CornerSelection """ TOP_EDGE = "t" RIGHT_EDGE = "r" BOTTOM_EDGE = "b" LEFT_EDGE = "l" def __init__(self, chamfer_select): self.top_edge = False self.right_edge = False self.bottom_edge = False self.left_edge = False if chamfer_select == 1: self.selectAll() CornerSelection.__init__(self, 1) return if chamfer_select == 0: CornerSelection.__init__(self, 0) return if type(chamfer_select) is dict: CornerSelection.__init__(self, chamfer_select) for key in chamfer_select: self[key] = bool(chamfer_select[key]) else: for i, value in enumerate(chamfer_select): self[i] = bool(value) def setLeft(self, value=1): CornerSelection.setLeft(self, value) self.left_edge = bool(value) def setTop(self, value=1): CornerSelection.setTop(self, value) self.top_edge = bool(value) def setRight(self, value=1): CornerSelection.setRight(self, value) self.right_edge = bool(value) def setBottom(self, value=1): CornerSelection.setBottom(self, value) self.bottom_edge = bool(value) def setCorners(self, value=1): self.top_left = bool(value) self.top_right = bool(value) self.bottom_right = bool(value) self.bottom_left = bool(value) def setEdges(self, value=1): self.top_edge = bool(value) self.right_edge = bool(value) self.bottom_edge = bool(value) self.left_edge = bool(value) def __len__(self): return 8 def __iter__(self): for v in CornerSelection.__iter__(self): yield v yield self.top_edge yield self.right_edge yield self.bottom_edge yield self.left_edge def __getitem__(self, item): if item in [4, ChamferSelPadGrid.TOP_EDGE]: return self.top_edge if item in [5, ChamferSelPadGrid.RIGHT_EDGE]: return self.right_edge if item in [6, ChamferSelPadGrid.BOTTOM_EDGE]: return self.bottom_edge if item in [7, ChamferSelPadGrid.LEFT_EDGE]: return self.left_edge return CornerSelection.__getitem__(self, item) def __setitem__(self, item, value): if item in [4, ChamferSelPadGrid.TOP_EDGE]: self.top_edge = bool(value) elif item in [5, ChamferSelPadGrid.RIGHT_EDGE]: self.right_edge = bool(value) elif item in [6, ChamferSelPadGrid.BOTTOM_EDGE]: self.bottom_edge = bool(value) elif item in [7, ChamferSelPadGrid.LEFT_EDGE]: self.left_edge = bool(value) else: CornerSelection.__setitem__(self, item, value) def to_dict(self): result = CornerSelection.to_dict(self) result.update({ ChamferSelPadGrid.TOP_EDGE: self.top_edge, ChamferSelPadGrid.RIGHT_EDGE: self.right_edge, ChamferSelPadGrid.BOTTOM_EDGE: self.bottom_edge, ChamferSelPadGrid.LEFT_EDGE: self.left_edge }) return result class ChamferedPadGrid(Node): r"""Add a ChamferedPad to the render tree :param \**kwargs: See below :Keyword Arguments: * *number* (``int``, ``str``) -- number/name of the pad (default: \"\") * *center* (``Vector2D``) -- center position of the pad grid * *size* (``float``, ``Vector2D``) -- size of the pads * *pincount* (``int``, ``[int, int]``) Pad count in x and y direction. If only one integer is given, it will be used for both directions. * *grid* (``float``, ``Vector2D``) Pad grid in x and y direction. If only one float is given, it will be used for both directions. * *solder_paste_margin_ratio* (``float``) -- solder paste margin ratio of the pad (default: 0) * *solder_paste_margin* (``float``) -- solder paste margin of the pad (default: 0) * *solder_mask_margin* (``float``) -- solder mask margin of the pad (default: 0) * *layers* (``Pad.LAYERS_SMT``, ``Pad.LAYERS_THT``, ``Pad.LAYERS_NPTH``) -- layers on which are used for the pad * *chamfer_selection* (``ChamferSelPadGrid``) -- Select which corner and edge pads to chamfer. * *chamfer_size* (``float``, ``Vector2D``) -- Size of the chamfer. * *x_mirror* (``[int, float](mirror offset)``) -- mirror x direction around offset "point" * *y_mirror* (``[int, float](mirror offset)``) -- mirror y direction around offset "point" * *radius_ratio* (``float``) -- The radius ratio of the rounded rectangle. (default 0 for backwards compatibility) * *maximum_radius* (``float``) -- The maximum radius for the rounded rectangle. If the radius produced by the radius_ratio parameter for the pad would exceed the maximum radius, the ratio is reduced to limit the radius. (This is useful for IPC-7351C compliance as it suggests 25% ratio with limit 0.25mm) * *round_radius_exact* (``float``) -- Set an exact round radius for a pad. * *round_radius_handler* (``RoundRadiusHandler``) -- An instance of the RoundRadiusHandler class If this is given then all other round radius specifiers are ignored """ def __init__(self, **kwargs): Node.__init__(self) if len(kwargs) == 0: return self.number = kwargs.get('number', "") self.center = Vector2D(kwargs.get('center', [0, 0])) self._initSize(**kwargs) self._initCount(**kwargs) self._initGrid(**kwargs) self._initPadSettings(**kwargs) def _initCount(self, **kwargs): if 'pincount' not in kwargs: raise KeyError('pincount not declared (like "pincount=10")') self.pincount = toIntArray(kwargs['pincount']) def _initSize(self, **kwargs): if 'size' not in kwargs: raise KeyError('size not declared (like "size=[1, 2]")') self.size = toVectorUseCopyIfNumber(kwargs['size'], low_limit=0) def _initGrid(self, **kwargs): if 'grid' not in kwargs: raise KeyError('grid not declared (like "grid=[1, 2]")') self.grid = toVectorUseCopyIfNumber(kwargs['grid'], low_limit=self.size) def _initPadSettings(self, **kwargs): if 'chamfer_selection' not in kwargs: raise KeyError('chamfer selection is required for chamfered pads (like "chamfer_selection=[1,0,0,0]")') self.chamfer_selection = ChamferSelPadGrid(kwargs.get('chamfer_selection')) if 'chamfer_size' not in kwargs: self.chamfer_size = Vector2D(0, 0) else: self.chamfer_size = toVectorUseCopyIfNumber( kwargs.get('chamfer_size'), low_limit=0, must_be_larger=False) if('round_radius_handler' in kwargs): self.round_radius_handler = kwargs['round_radius_handler'] else: # default radius ration 0 for backwards compatibility self.round_radius_handler = RoundRadiusHandler(default_radius_ratio=0, **kwargs) self.padargs = copy(kwargs) self.padargs.pop('size', None) self.padargs.pop('number', None) self.padargs.pop('at', None) self.padargs.pop('chamfer_size', None) self.padargs.pop('round_radius_handler', None) def chamferAvoidCircle(self, center, diameter, clearance=0): r""" set the chamfer such that the pad avoids a cricle located at near corner. :param center: (``Vector2D``) -- The center of the circle ot avoid :param diameter: (``float``, ``Vector2D``) -- The diameter of the circle. If Vector2D given only x direction is used. :param clearance: (``float``) -- Additional clearance around circle. default:0 """ relative_center = Vector2D(center) - self.center left = -self.grid['x']*(self.pincount[0]-1)/2 top = -self.grid['y']*(self.pincount[1]-1)/2 nearest_x = left nearest_y = top min_dist_x = abs(relative_center['x']-nearest_x) min_dist_y = abs(relative_center['y']-nearest_y) for i in range(self.pincount[0]): x = left+i*self.grid['x'] dx = abs(x-relative_center['x']) if dx < min_dist_x: min_dist_x = dx nearest_x = x for i in range(self.pincount[1]): y = top+i*self.grid['y'] dy = abs(y-relative_center['y']) if dy < min_dist_y: min_dist_y = dy nearest_y = y temp_pad = ChamferedPad( at=[nearest_x, nearest_y], size=self.size, type=Pad.TYPE_SMT, layers=['F.Cu'], corner_selection=1 ) self.chamfer_size = temp_pad.chamferAvoidCircle( center=relative_center, diameter=diameter, clearance=clearance) return self.chamfer_size def __padCornerSelection(self, idx_x, idx_y): corner = CornerSelection(0) if idx_x == 0: if idx_y == 0: if self.chamfer_selection[ChamferSelPadGrid.TOP_LEFT]: corner[CornerSelection.TOP_LEFT] = True if self.chamfer_selection[ChamferSelPadGrid.LEFT_EDGE]: corner[CornerSelection.BOTTOM_LEFT] = True if idx_y == self.pincount[1]-1: if self.chamfer_selection[ChamferSelPadGrid.BOTTOM_LEFT]: corner[CornerSelection.BOTTOM_LEFT] = True if self.chamfer_selection[ChamferSelPadGrid.LEFT_EDGE]: corner[CornerSelection.TOP_LEFT] = True if idx_y != 0 and idx_y != self.pincount[1]-1: if self.chamfer_selection[ChamferSelPadGrid.LEFT_EDGE]: corner.setLeft() if idx_x == self.pincount[0]-1: if idx_y == 0: if self.chamfer_selection[ChamferSelPadGrid.TOP_RIGHT]: corner[CornerSelection.TOP_RIGHT] = True if self.chamfer_selection[ChamferSelPadGrid.RIGHT_EDGE]: corner[CornerSelection.BOTTOM_RIGHT] = True if idx_y == self.pincount[1]-1: if self.chamfer_selection[ChamferSelPadGrid.BOTTOM_RIGHT]: corner[CornerSelection.BOTTOM_RIGHT] = True if self.chamfer_selection[ChamferSelPadGrid.RIGHT_EDGE]: corner[CornerSelection.TOP_RIGHT] = True if idx_y != 0 and idx_y != self.pincount[1]-1: if self.chamfer_selection[ChamferSelPadGrid.RIGHT_EDGE]: corner.setRight() if idx_x != 0 and idx_x != self.pincount[0]-1: if idx_y == 0: if self.chamfer_selection[ChamferSelPadGrid.TOP_EDGE]: corner.setTop() if idx_y == self.pincount[1]-1: if self.chamfer_selection[ChamferSelPadGrid.BOTTOM_EDGE]: corner.setBottom() return corner def _generatePads(self): left = -self.grid['x']*(self.pincount[0]-1)/2+self.center['x'] top = -self.grid['y']*(self.pincount[1]-1)/2+self.center['y'] pads = [] for idx_x in range(self.pincount[0]): x = left+idx_x*self.grid['x'] for idx_y in range(self.pincount[1]): y = top+idx_y*self.grid['y'] corner = self.__padCornerSelection(idx_x, idx_y) pads.append(ChamferedPad( at=[x, y], number=self.number, size=self.size, chamfer_size=self.chamfer_size, corner_selection=corner, round_radius_handler=self.round_radius_handler, **self.padargs )) return pads def getVirtualChilds(self): return self._generatePads() def __copy__(self): newone = type(self)() newone.__dict__.update(self.__dict__) return newone ================================================ FILE: KicadModTree/nodes/specialized/ExposedPad.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2017 by @SchrodingersGat # (C) 2017 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr from __future__ import division from KicadModTree.util.paramUtil import * from KicadModTree.nodes.base.Pad import * from KicadModTree.nodes.specialized.ChamferedPadGrid import * from KicadModTree.nodes.specialized.PadArray import * from KicadModTree.nodes.Node import Node from math import sqrt, floor from copy import copy import traceback class ExposedPad(Node): r"""Add an exposed pad Complete with correct paste, mask and via handling :param \**kwargs: See below :Keyword Arguments: * *number* (``int``, ``str``) -- number/name of the pad * *at* (``Vector2D``) -- center the exposed pad around this point (default: 0,0) * *size* (``float``, ``Vector2D``) -- size of the pad * *solder_mask_margin* (``float``) -- solder mask margin of the pad (default: 0) Only used if mask_size is not specified. * *mask_size* (``float``, ``Vector2D``) -- size of the mask cutout (If not given, mask will be part of the main pad) * *paste_layout* (``int``, ``[int, int]``) -- paste layout specification. How many pads in x and y direction. If only a single integer given, x and y direction use the same count. * *paste_between_vias* (``int``, ``[int, int]``) Alternative for paste_layout with more controll. This defines how many pads will be between 4 vias in x and y direction. If only a single integer given, x and y direction use the same count. * *paste_rings_outside* (``int``, ``[int, int]``) Alternative for paste_layout with more controll. Defines the number of rings outside of the vias in x and y direction. If only a single integer given, x and y direction use the same count. * *paste_coverage* (``float``) -- how much of the mask free area is covered with paste. (default: 0.65) * *via_layout* (``int``, ``[int, int]``) -- thermal via layout specification. How many vias in x and y direction. If only a single integer given, x and y direction use the same count. default: no vias added * *via_grid* (``int``, ``Vector2D``) -- thermal via grid specification. Grid used for thermal vias in x and y direction. If only a single integer given, x and y direction use the same count. If none is given then the via grid will be automatically calculated to have them distributed across the main pad. * *via_drill* (``float``) -- via drill diameter (default: 0.3) * *via_tented* (VIA_TENTED, VIA_TENTED_TOP_ONLY, VIA_TENTED_BOTTOM_ONLY, VIA_NOT_TENTED) -- Determines which side of the thermal vias is covered in soldermask. On the top only vias outside the defined mask area can be covered in soldermask. default: VIA_TENTED * *min_annular_ring* (``float``) -- Anullar ring for thermal vias. (default: 0.15) * *bottom_pad_Layers* (``[layer string]``) -- Select layers for the bottom pad (default: [B.Cu]) -- Ignored if no thermal vias are added. If None or empty no pad is added. * *bottom_pad_min_size* (``float``, ``Vector2D``) -- Minimum size for bottom pad. default: (0,0) Ignored if no bottom pad given. * *paste_avoid_via* (``bool``) -- Paste automatically generated to avoid vias (default: false) * *via_paste_clarance* (``float``) Clearance between paste and via drills (default: 0.05) Only used if paste_avoid_via is set. * *grid_round_base* (``float``) -- Base used for rounding calculated grids (default: 0.01) 0 means no rounding * *size_round_base* (``float``) -- Base used for rounding calculated sizes (default: 0.01) 0 means no rounding * *radius_ratio* (``float``) -- The radius ratio of the main pads. * *maximum_radius* (``float``) -- The maximum radius for the main pads. If the radius produced by the radius_ratio parameter for the pad would exceed the maximum radius, the ratio is reduced to limit the radius. * *round_radius_exact* (``float``) -- Set an exact round radius for the main pads. * *paste_radius_ratio* (``float``) -- The radius ratio of the paste pads. * *paste_maximum_radius* (``float``) -- The maximum radius for the paste pads. If the radius produced by the paste_radius_ratio parameter for the paste pad would exceed the maximum radius, the ratio is reduced to limit the radius. * *paste_round_radius_exact* (``float``) -- Set an exact round radius for the paste pads. * *kicad4_compatible* (``bool``) -- Makes sure the resulting pad is compatible with kicad 4. default False """ VIA_TENTED = 'all' VIA_TENTED_TOP_ONLY = 'top' VIA_TENTED_BOTTOM_ONLY = 'bottom' VIA_NOT_TENTED = 'none' def __init__(self, **kwargs): Node.__init__(self) self.at = Vector2D(kwargs.get('at', [0, 0])) self.size_round_base = kwargs.get('size_round_base', 0.01) self.grid_round_base = kwargs.get('grid_round_base', 0.01) self.round_radius_handler = RoundRadiusHandler(default_radius_ratio=0, **kwargs) self.kicad4_compatible = kwargs.get('kicad4_compatible', False) self.paste_round_radius_handler = RoundRadiusHandler( radius_ratio=kwargs.get('paste_radius_ratio', 0), maximum_radius=kwargs.get('paste_maximum_radius', None), round_radius_exact=kwargs.get('paste_round_radius_exact', None), kicad4_compatible=self.kicad4_compatible ) self._initNumber(**kwargs) self._initSize(**kwargs) self._initThermalVias(**kwargs) self._initPaste(**kwargs) def _initNumber(self, **kwargs): if not kwargs.get('number'): raise KeyError('pad number for exposed pad not declared (like "number=9")') self.number = kwargs.get('number') def _initSize(self, **kwargs): if not kwargs.get('size'): raise KeyError('pad size not declared (like "size=[1,1]")') self.size = toVectorUseCopyIfNumber(kwargs.get('size')) if not kwargs.get('mask_size'): self.mask_size = self.size else: self.mask_size = toVectorUseCopyIfNumber(kwargs.get('mask_size')) def setViaLayout(self, layout): self.has_vias = True self.via_layout = toIntArray(layout, min_value=0) if self.via_layout[0] == 0 or self.via_layout[1] == 0: self.has_vias = False return self.has_vias def __initViaGrid(self, **kwargs): nx = self.via_layout[0]-1 ny = self.via_layout[1]-1 self.via_grid = kwargs.get('via_grid') if self.via_grid is not None: self.via_grid = toVectorUseCopyIfNumber(self.via_grid, low_limit=self.via_size) else: self.via_grid = Vector2D([ (self.size.x-self.via_size)/(nx if nx > 0 else 1), (self.size.y-self.via_size)/(ny if ny > 0 else 1) ]) self.via_grid = self.via_grid.round_to(kwargs.get('grid_round_base', 0)) def _initThermalVias(self, **kwargs): if not self.setViaLayout(kwargs.get('via_layout', [0, 0])): return self.via_drill = kwargs.get('via_drill', 0.3) self.via_size = self.via_drill + 2*kwargs.get('min_annular_ring', 0.15) self.__initViaGrid(**kwargs) self.via_tented = kwargs.get('via_tented', ExposedPad.VIA_TENTED) self.bottom_pad_Layers = kwargs.get('bottom_pad_Layers', ['B.Cu']) self.add_bottom_pad = True if self.bottom_pad_Layers is None or len(self.bottom_pad_Layers) == 0: self.add_bottom_pad = False else: bottom_pad_min_size = toVectorUseCopyIfNumber(kwargs.get('bottom_pad_min_size', [0, 0])) self.bottom_size = Vector2D([ max((self.via_layout[0]-1)*self.via_grid[0]+self.via_size, bottom_pad_min_size[0]), max((self.via_layout[1]-1)*self.via_grid[1]+self.via_size, bottom_pad_min_size[1]) ]) def __viasInMaskCount(self, idx): r""" Determine the number of vias within the soldermask area :param idx: (``int``) -- determines if the x or y direction is used. """ if (self.via_layout[idx]-1)*self.via_grid[idx] <= self.paste_area_size[idx]: return self.via_layout[idx] else: return int(self.paste_area_size[idx]//(self.via_grid[idx])) def _initPasteForAvoidingVias(self, **kwargs): self.via_clarance = kwargs.get('via_paste_clarance', 0.05) # check get against none to allow the caller to use None as the sign to ignore these. if kwargs.get('paste_between_vias') is not None\ or kwargs.get('paste_rings_outside')is not None: self.paste_between_vias = toIntArray(kwargs.get('paste_between_vias', [0, 0]), min_value=0) self.paste_rings_outside = toIntArray(kwargs.get('paste_rings_outside', [0, 0]), min_value=0) else: default = [l-1 for l in self.via_layout] layout = kwargs.get('paste_layout') if layout is None: # alows initializing with 'paste_layout=None' to force default value layout = default self.paste_layout = toIntArray(layout) # int(floor(paste_count/(vias_in_mask-1))) self.paste_between_vias = [p//(v-1) if v > 1 else p//v for p, v in zip(self.paste_layout, self.vias_in_mask)] inner_count = [(v-1)*p for v, p in zip(self.vias_in_mask, self.paste_between_vias)] self.paste_rings_outside = [(p-i)//2 for p, i in zip(self.paste_layout, inner_count)] def _initPaste(self, **kwargs): self.paste_avoid_via = kwargs.get('paste_avoid_via', False) self.paste_reduction = sqrt(kwargs.get('paste_coverage', 0.65)) self.paste_area_size = Vector2D([min(m, c) for m, c in zip(self.mask_size, self.size)]) if self.has_vias: self.vias_in_mask = [self.__viasInMaskCount(i) for i in range(2)] if not self.has_vias or not all(self.vias_in_mask): self.paste_avoid_via = False if self.has_vias and self.paste_avoid_via: self._initPasteForAvoidingVias(**kwargs) else: self.paste_layout = toIntArray(kwargs.get('paste_layout', [1, 1])) def __createPasteIgnoreVia(self): nx = self.paste_layout[0] ny = self.paste_layout[1] sx = self.paste_area_size.x sy = self.paste_area_size.y paste_size = Vector2D([sx*self.paste_reduction/nx, sy*self.paste_reduction/ny])\ .round_to(self.size_round_base) dx = (sx - paste_size[0]*nx)/(nx) dy = (sy - paste_size[1]*ny)/(ny) paste_grid = Vector2D( [paste_size[0]+dx, paste_size[1]+dy] ).round_to(self.grid_round_base) return [ChamferedPadGrid( number="", type=Pad.TYPE_SMT, center=self.at, size=paste_size, layers=['F.Paste'], chamfer_size=0, chamfer_selection=0, pincount=self.paste_layout, grid=paste_grid, round_radius_handler=self.paste_round_radius_handler )] @staticmethod def __createPasteGrids(original, grid, count, center): r""" Helper function for creating grids of ChamferedPadGrid sections :param original: (``ChamferedPadGrid``) -- This instance will be shallow copied to create a grid. :param grid: (``float``, ``Vector2D``) -- The spacing between instances :param count: (``int``, ``[int, int]``) -- Determines how many copies will be created in x and y direction. If only one number is given, both directions use the same count. :parma center: (``float``, ``Vector2D``) -- Center of the resulting grid of grids. """ pads = [] top_left = Vector2D(center)-Vector2D(grid)*(Vector2D(count)-1)/2 for idx_x in range(count[0]): x = top_left[0]+idx_x*grid[0] for idx_y in range(count[1]): y = top_left[1]+idx_y*grid[1] pads.append(copy(original)) pads[-1].center = Vector2D(x, y) return pads def __createPasteAvoidViasInside(self): top_left_area = self.top_left_via+self.via_grid/2 self.inner_grid = self.via_grid/Vector2D(self.paste_between_vias) if any(self.paste_rings_outside): self.inner_size = self.via_grid/Vector2D(self.paste_between_vias)*self.paste_reduction else: # inner_grid = mask_size/(inner_count) self.inner_size = self.paste_area_size/(self.inner_count)*self.paste_reduction corner = ChamferSelPadGrid(0) corner.setCorners() pad = ChamferedPadGrid( number="", type=Pad.TYPE_SMT, center=[0, 0], size=self.inner_size, layers=['F.Paste'], chamfer_size=0, chamfer_selection=corner, pincount=self.paste_between_vias, grid=self.inner_grid, round_radius_handler=self.paste_round_radius_handler ) if not self.kicad4_compatible: pad.chamferAvoidCircle( center=self.via_grid/2, diameter=self.via_drill, clearance=self.via_clarance) count = [self.vias_in_mask[0]-1, self.vias_in_mask[1]-1] return ExposedPad.__createPasteGrids( original=pad, grid=self.via_grid, count=count, center=self.at ) def __createPasteOutsideX(self): pads = [] corner = ChamferSelPadGrid( {ChamferSelPadGrid.TOP_RIGHT: 1, ChamferSelPadGrid.BOTTOM_RIGHT: 1 }) x = self.top_left_via[0]-self.ring_size[0]/2 y = self.at[1]-(self.via_layout[1]-2)/2*self.via_grid[1] pad_side = ChamferedPadGrid( number="", type=Pad.TYPE_SMT, center=[x, y], size=[self.outer_size[0], self.inner_size[1]], layers=['F.Paste'], chamfer_size=0, chamfer_selection=corner, pincount=[self.paste_rings_outside[0], self.paste_between_vias[1]], grid=[self.outer_paste_grid[0], self.inner_grid[1]], round_radius_handler=self.paste_round_radius_handler ) if not self.kicad4_compatible: pad_side.chamferAvoidCircle( center=self.top_left_via, diameter=self.via_drill, clearance=self.via_clarance) pads.extend(ExposedPad.__createPasteGrids( original=pad_side, grid=self.via_grid, count=[1, self.via_layout[1]-1], center=[x, self.at['y']] )) corner = ChamferSelPadGrid( {ChamferSelPadGrid.TOP_LEFT: 1, ChamferSelPadGrid.BOTTOM_LEFT: 1 }) pad_side.chamfer_selection = corner x = 2*self.at[0]-x pads.extend(ExposedPad.__createPasteGrids( original=pad_side, grid=self.via_grid, count=[1, self.via_layout[1]-1], center=[x, self.at['y']] )) return pads def __createPasteOutsideY(self): pads = [] corner = ChamferSelPadGrid( {ChamferSelPadGrid.BOTTOM_LEFT: 1, ChamferSelPadGrid.BOTTOM_RIGHT: 1 }) x = self.at[0]-(self.via_layout[0]-2)/2*self.via_grid[0] y = self.top_left_via[1]-self.ring_size[1]/2 pad_side = ChamferedPadGrid( number="", type=Pad.TYPE_SMT, center=[x, y], size=[self.inner_size[0], self.outer_size[1]], layers=['F.Paste'], chamfer_size=0, chamfer_selection=corner, pincount=[self.paste_between_vias[0], self.paste_rings_outside[1]], grid=[self.inner_grid[0], self.outer_paste_grid[1]], round_radius_handler=self.paste_round_radius_handler ) if not self.kicad4_compatible: pad_side.chamferAvoidCircle( center=self.top_left_via, diameter=self.via_drill, clearance=self.via_clarance) pads.extend(ExposedPad.__createPasteGrids( original=pad_side, grid=self.via_grid, count=[self.via_layout[0]-1, 1], center=[self.at['x'], y] )) corner = ChamferSelPadGrid( {ChamferSelPadGrid.TOP_LEFT: 1, ChamferSelPadGrid.TOP_RIGHT: 1 }) pad_side.chamfer_selection = corner y = 2*self.at[1]-y pads.extend(ExposedPad.__createPasteGrids( original=pad_side, grid=self.via_grid, count=[self.via_layout[0]-1, 1], center=[self.at['x'], y] )) return pads def __createPasteOutsideCorners(self): pads = [] left = self.top_left_via[0]-self.ring_size[0]/2 top = self.top_left_via[1]-self.ring_size[1]/2 corner = [ [ {ChamferSelPadGrid.BOTTOM_RIGHT: 1}, {ChamferSelPadGrid.TOP_RIGHT: 1} ], [ {ChamferSelPadGrid.BOTTOM_LEFT: 1}, {ChamferSelPadGrid.TOP_LEFT: 1} ] ] pad_side = ChamferedPadGrid( number="", type=Pad.TYPE_SMT, center=[left, top], size=self.outer_size, layers=['F.Paste'], chamfer_size=0, chamfer_selection=0, pincount=self.paste_rings_outside, grid=self.outer_paste_grid, round_radius_handler=self.paste_round_radius_handler ) if not self.kicad4_compatible: pad_side.chamferAvoidCircle( center=self.top_left_via, diameter=self.via_drill, clearance=self.via_clarance) for idx_x in range(2): for idx_y in range(2): x = left if idx_x == 0 else 2*self.at[0]-left y = top if idx_y == 0 else 2*self.at[1]-top pad_side.center = Vector2D(x, y) pad_side.chamfer_selection = ChamferSelPadGrid(corner[idx_x][idx_y]) pads.append(copy(pad_side)) return pads def __createPasteAvoidViasOutside(self): self.ring_size = (self.paste_area_size-(Vector2D(self.vias_in_mask)-1)*self.via_grid)/2 self.outer_paste_grid = Vector2D([s/p if p != 0 else s for s, p in zip(self.ring_size, self.paste_rings_outside)]) self.outer_size = self.outer_paste_grid*self.paste_reduction pads = [] if self.paste_rings_outside[0] and self.inner_count[1] > 0: pads.extend(self.__createPasteOutsideX()) if self.paste_rings_outside[1] and self.inner_count[0]: pads.extend(self.__createPasteOutsideY()) if all(self.paste_rings_outside): pads.extend(self.__createPasteOutsideCorners()) return pads def __createPaste(self): pads = [] if self.has_vias: self.top_left_via = -(Vector2D(self.vias_in_mask)-1)*self.via_grid/2+self.at if self.has_vias and self.paste_avoid_via: self.inner_count = (Vector2D(self.vias_in_mask)-1)*Vector2D(self.paste_between_vias) if all(self.vias_in_mask) and all(self.paste_between_vias): pads += self.__createPasteAvoidViasInside() if any(self.paste_rings_outside): pads += self.__createPasteAvoidViasOutside() else: pads += self.__createPasteIgnoreVia() return pads def __createMainPad(self): pads = [] if self.size == self.mask_size: layers_main = ['F.Cu', 'F.Mask'] else: layers_main = ['F.Cu'] pads.append(Pad( number="", at=self.at, size=self.mask_size, shape=Pad.SHAPE_ROUNDRECT, type=Pad.TYPE_SMT, layers=['F.Mask'], round_radius_handler=self.round_radius_handler )) pads.append(Pad( number=self.number, at=self.at, size=self.size, shape=Pad.SHAPE_ROUNDRECT, type=Pad.TYPE_SMT, layers=layers_main, round_radius_handler=self.round_radius_handler )) return pads def __createVias(self): via_layers = ['*.Cu'] if self.via_tented == ExposedPad.VIA_NOT_TENTED or self.via_tented == ExposedPad.VIA_TENTED_BOTTOM_ONLY: via_layers.append('F.Mask') if self.via_tented == ExposedPad.VIA_NOT_TENTED or self.via_tented == ExposedPad.VIA_TENTED_TOP_ONLY: via_layers.append('B.Mask') pads = [] cy = -((self.via_layout[1]-1)*self.via_grid[1])/2 + self.at.y for i in range(self.via_layout[1]): pads.append( PadArray(center=[self.at.x, cy], initial=self.number, increment=0, pincount=self.via_layout[0], x_spacing=self.via_grid[0], size=self.via_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, drill=self.via_drill, layers=via_layers )) cy += self.via_grid[1] if self.add_bottom_pad: pads.append(Pad( number=self.number, at=self.at, size=self.bottom_size, shape=Pad.SHAPE_ROUNDRECT, type=Pad.TYPE_SMT, layers=self.bottom_pad_Layers, round_radius_handler=self.round_radius_handler )) return pads def getVirtualChilds(self): # traceback.print_stack() if self.has_vias: self.round_radius_handler.limitMaxRadius(self.via_size/2) pads = [] pads += self.__createMainPad() if self.has_vias: pads += self.__createVias() pads += self.__createPaste() return pads def getRoundRadius(self): return self.round_radius_handler.getRoundRadius(min(self.size)) ================================================ FILE: KicadModTree/nodes/specialized/FilledRect.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node from KicadModTree.nodes.specialized import RectLine from KicadModTree.nodes.specialized import RectFill class FilledRect(Node): r"""Add a Filled Rect to the render tree Combines ``RectLine`` and ``RectFill`` into one class for simpler handling :param \**kwargs: See below :Keyword Arguments: * *start* (``Vector2D``) -- start edge of the rect * *end* (``Vector2D``) -- end edge of the rect * *layer* (``str``) -- layer on which the rect is drawn (default: 'F.SilkS') * *width* (``float``) -- width of the outer line (default: 0.15) :Example: >>> from KicadModTree import * >>> FilledRect(start=[-3, -2], end=[3, 2], layer='F.SilkS') """ def __init__(self, **kwargs): Node.__init__(self) self.start_pos = Vector2D(kwargs['start']) self.end_pos = Vector2D(kwargs['end']) self.layer = kwargs.get('layer', 'F.SilkS') self.width = kwargs.get('width', 0.12) # TODO: better variation to get line width rect_line = RectLine(**kwargs) rect_line._parent = self rect_fill = RectFill(**kwargs) rect_fill._parent = self self.virtual_childs = [rect_line, rect_fill] def getVirtualChilds(self): return self.virtual_childs def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_string = ['start: [x: {sx}, y: {sy}]'.format(sx=self.start_pos.x, sy=self.start_pos.y), 'end: [x: {ex}, y: {ey}]'.format(ex=self.end_pos.x, ey=self.end_pos.y)] render_text += " [{}]".format(", ".join(render_string)) return render_text ================================================ FILE: KicadModTree/nodes/specialized/PadArray.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2017 by @SchrodingersGat # (C) 2017 by Thomas Pointhuber, from types import GeneratorType from KicadModTree.nodes.base.Pad import * from KicadModTree.nodes.specialized.ChamferedPad import * from KicadModTree.nodes.Node import Node from KicadModTree.util.paramUtil import * class PadArray(Node): r"""Add a row of Pads Simplifies the handling of pads which are rendered in a specific form :param \**kwargs: See below :Keyword Arguments: * *start* (``Vector2D``) -- start edge of the pad array * *center* (``Vector2D``) -- center pad array around specific point * *pincount* (``int``) -- number of pads to render * *spacing* (``Vector2D``, ``float``) -- offset between rendered pads * *x_spacing* (``float``) -- x offset between rendered pads * *y_spacing* (``float``) -- y offset between rendered pads * *initial* (``int``) -- name of the first pad * *increment* (``int, function(previous_number)``) -- declare how the name of the follow up is calculated * *type* (``Pad.TYPE_THT``, ``Pad.TYPE_SMT``, ``Pad.TYPE_CONNECT``, ``Pad.TYPE_NPTH``) -- type of the pad * *shape* (``Pad.SHAPE_CIRCLE``, ``Pad.SHAPE_OVAL``, ``Pad.SHAPE_RECT``, ``Pad.SHAPE_TRAPEZE``, ...) -- shape of the pad * *rotation* (``float``) -- rotation of the pad * *size* (``float``, ``Vector2D``) -- size of the pad * *offset* (``Vector2D``) -- offset of the pad * *drill* (``float``, ``Vector2D``) -- drill-size of the pad * *solder_paste_margin_ratio* (``float``) -- solder paste margin ratio of the pad * *layers* (``Pad.LAYERS_SMT``, ``Pad.LAYERS_THT``, ``Pad.LAYERS_NPTH``) -- layers on which are used for the pad * *chamfer_corner_selection_first* (``[bool, bool, bool, bool]``) Select which corner should be chamfered for the first pad. (default: None) * *chamfer_corner_selection_last* (``[bool, bool, bool, bool]``) Select which corner should be chamfered for the last pad. (default: None) * *chamfer_size* (``float``, ``Vector2D``) -- size for the chamfer used for the end pads. (default: None) * *end_pads_size_reduction* (``dict with keys x-,x+,y-,y+``) -- size is reduced on the given side. (size reduced plus center moved.) * *tht_pad1_shape* (``Pad.SHAPE_RECT``, ``Pad.SHAPE_ROUNDRECT``, ...) -- shape for marking pad 1 for through hole components. (deafult: ``Pad.SHAPE_ROUNDRECT``) * *tht_pad1_id* (``int, string``) -- pad number used for "pin 1" (default: 1) * *hidden_pins* (``int, Vector1D``) -- pin number(s) to be skipped; a footprint with hidden pins has missing pads and matching pin numbers * *deleted_pins* (``int, Vector1D``) -- pin locations(s) to be skipped; a footprint with deleted pins has pads missing but no missing pin numbers" :Example: >>> from KicadModTree import * >>> PadArray(pincount=10, spacing=[1,-1], center=[0,0], initial=5, increment=2, ... type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[1,2], layers=Pad.LAYERS_SMT) """ def __init__(self, **kwargs): Node.__init__(self) self._initPincount(**kwargs) self._initIncrement(**kwargs) self._initInitialNumber(**kwargs) self._initSpacing(**kwargs) self._initStartingPosition(**kwargs) self.virtual_childs = self._createPads(**kwargs) # How many pads in the array def _initPincount(self, **kwargs): if not kwargs.get('pincount'): raise KeyError('pincount not declared (like "pincount=10")') self.pincount = kwargs.get('pincount') if type(self.pincount) is not int or self.pincount <= 0: raise ValueError('{pc} is an invalid value for pincount'.format(pc=self.pincount)) if kwargs.get('hidden_pins') and kwargs.get('deleted_pins'): raise KeyError('hidden pins and deleted pins cannot be used together') self.exclude_pin_list = [] if kwargs.get('hidden_pins'): # exclude_pin_list is for pads being removed based on pad number # deleted pins are filtered out later by pad location (not number) self.exclude_pin_list = kwargs.get('hidden_pins') if type(self.exclude_pin_list) not in [list, tuple]: raise TypeError('exclude pin list must be specified like "exclude_pin_list=[0,1]"') elif any([type(i) not in [int] for i in self.exclude_pin_list]): raise ValueError('exclude pin list must be integer value') # Where to start the aray def _initStartingPosition(self, **kwargs): """ can use the 'start' argument to start a pad array at a given position OR can use the 'center' argument to center the array around the given position """ self.startingPosition = [0, 0] # Start takes priority if kwargs.get('start'): self.startingPosition = kwargs.get('start') if type(self.startingPosition) not in [list, tuple] or not len(self.startingPosition) == 2: raise ValueError('array starting position "start" must be given as an list of length two') if any([type(i) not in [int, float] for i in self.startingPosition]): raise ValueError('array starting coordinates must be numerical') elif kwargs.get('center'): center = kwargs.get('center') if type(center) not in [list, tuple] or not len(center) == 2: raise ValueError('array center position "center" must be given as a list of length two') if any([type(i) not in [int, float] for i in center]): raise ValueError('array center coordinates must be numerical') # Now calculate the desired starting position of the array self.startingPosition[0] = center[0] - (self.pincount - 1) * self.spacing[0] / 2. self.startingPosition[1] = center[1] - (self.pincount - 1) * self.spacing[1] / 2. # What number to start with? def _initInitialNumber(self, **kwargs): self.initialPin = kwargs.get('initial', 1) if self.initialPin == "": self.increment = 0 elif type(self.initialPin) is not int or self.initialPin < 1: if not callable(self.increment): raise ValueError('{pn} is not a valid starting pin number if increment is not a function' .format(pn=self.initialPin)) # Pin incrementing def _initIncrement(self, **kwargs): self.increment = kwargs.get('increment', 1) # Pad spacing def _initSpacing(self, **kwargs): """ spacing can be given as: spacing = [1,2] # high priority x_spacing = 1 y_spacing = 2 """ self.spacing = [0, 0] # [x, y] if kwargs.get('spacing'): self.spacing = kwargs.get('spacing') if type(self.spacing) not in [list, tuple]: raise TypeError('spacing must be specified like "spacing=[0,1]"') elif len(self.spacing) is not 2: raise ValueError('spacing must be supplied as x,y pair') elif any([type(i) not in [int, float] for i in self.spacing]): raise ValueError('spacing must be numerical value') # if 'spacing' is specified, ignore x_spacing and y_spacing return if kwargs.get('x_spacing'): self.spacing[0] = kwargs.get('x_spacing') if type(self.spacing[0]) not in [int, float]: raise ValueError('x_spacing must be supplied as numerical value') if kwargs.get('y_spacing'): self.spacing[1] = kwargs.get('y_spacing') if type(self.spacing[1]) not in [int, float]: raise ValueError('y_spacing must be supplied as numerical value') if all([i == 0 for i in self.spacing]): raise ValueError('pad spacing ({sp}) must be non-zero'.format(sp=self.spacing)) def _createPads(self, **kwargs): pads = [] x_start, y_start = self.startingPosition x_spacing, y_spacing = self.spacing padShape = kwargs.get('shape') # Special case, increment = 0 # this can be used for creating an array with all the same pad number if self.increment == 0: pad_numbers = [self.initialPin] * self.pincount elif type(self.increment) == int: pad_numbers = range(self.initialPin, self.initialPin + (self.pincount * self.increment), self.increment) elif callable(self.increment): pad_numbers = [self.initialPin] for idx in range(1, self.pincount): pad_numbers.append(self.increment(pad_numbers[-1])) elif type(self.increment) == GeneratorType: pad_numbers = [next(self.increment) for i in range(self.pincount)] else: raise TypeError("Wrong type for increment. It must be either a int, callable or generator.") end_pad_params = copy(kwargs) if kwargs.get('end_pads_size_reduction'): size_reduction = kwargs['end_pads_size_reduction'] end_pad_params['size'] = toVectorUseCopyIfNumber(kwargs.get('size'), low_limit=0) delta_size = Vector2D( size_reduction.get('x+', 0) + size_reduction.get('x-', 0), size_reduction.get('y+', 0) + size_reduction.get('y-', 0) ) end_pad_params['size'] -= delta_size delta_pos = Vector2D( -size_reduction.get('x+', 0) + size_reduction.get('x-', 0), -size_reduction.get('y+', 0) + size_reduction.get('y-', 0) )/2 else: delta_pos = Vector2D(0, 0) for i, number in enumerate(pad_numbers): includePad = True # deleted pins are filtered by pad/pin position (they are 'None' in pad_numbers list) if type(number) not in [int, str]: includePad = False # hidden pins are filtered out by pad number (index of pad_numbers list) if not kwargs.get('deleted_pins'): if type(self.initialPin) == 'int': includePad = (self.initialPin + i) not in self.exclude_pin_list else: includePad = number not in self.exclude_pin_list if includePad: current_pad_pos = Vector2D( x_start + i * x_spacing, y_start + i * y_spacing ) current_pad_params = copy(kwargs) if i == 0 or i == len(pad_numbers)-1: current_pad_pos += delta_pos current_pad_params = end_pad_params if kwargs.get('type') == Pad.TYPE_THT and number == kwargs.get('tht_pad1_id', 1): current_pad_params['shape'] = kwargs.get('tht_pad1_shape', Pad.SHAPE_ROUNDRECT) if 'radius_ratio' not in current_pad_params: current_pad_params['radius_ratio'] = 0.25 if 'maximum_radius' not in current_pad_params: current_pad_params['maximum_radius'] = 0.25 else: current_pad_params['shape'] = padShape if kwargs.get('chamfer_size'): if i == 0 and 'chamfer_corner_selection_first' in kwargs: pads.append( ChamferedPad( number=number, at=current_pad_pos, corner_selection=kwargs.get('chamfer_corner_selection_first'), **current_pad_params )) continue if i == len(pad_numbers)-1 and 'chamfer_corner_selection_last' in kwargs: pads.append( ChamferedPad( number=number, at=current_pad_pos, corner_selection=kwargs.get('chamfer_corner_selection_last'), **current_pad_params )) continue pads.append(Pad(number=number, at=current_pad_pos, **current_pad_params)) return pads def getVirtualChilds(self): return self.virtual_childs ================================================ FILE: KicadModTree/nodes/specialized/PolygoneLine.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.PolygonPoints import * from KicadModTree.nodes.Node import Node from KicadModTree.nodes.base.Line import Line class PolygoneLine(Node): r"""Add a Polygone Line to the render tree :param \**kwargs: See below :Keyword Arguments: * *polygone* (``list(Point)``) -- edges of the polygone * *layer* (``str``) -- layer on which the polygone is drawn (default: 'F.SilkS') * *width* (``float``) -- width of the line (default: None, which means auto detection) :Example: >>> from KicadModTree import * >>> PolygoneLine(polygone=[[0, 0], [0, 1], [1, 1], [0, 0]], layer='F.SilkS') """ def __init__(self, **kwargs): Node.__init__(self) self.layer = kwargs.get('layer', 'F.SilkS') self.width = kwargs.get('width') self._initPolyPoint(**kwargs) self.virtual_childs = self._createChildNodes(self.nodes) def _initPolyPoint(self, **kwargs): self.nodes = PolygonPoints(**kwargs) def _createChildNodes(self, polygone_line): nodes = [] for line_start, line_end in zip(polygone_line, polygone_line[1:]): new_node = Line(start=line_start, end=line_end, layer=self.layer, width=self.width) new_node._parent = self nodes.append(new_node) return nodes def getVirtualChilds(self): return self.virtual_childs def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_text += " [" node_strings = [] for node in self.nodes: node_position = Vector2D(node) node_strings.append("[x: {x}, y: {y}]".format(x=node_position.x, y=node_position.y)) if len(node_strings) <= 6: render_text += " ,".join(node_strings) else: # display only a few nodes of the beginning and the end of the polygone line render_text += " ,".join(node_strings[:3]) render_text += " ,... ," render_text += " ,".join(node_strings[-3:]) render_text += "]" return render_text ================================================ FILE: KicadModTree/nodes/specialized/RectFill.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node from KicadModTree.nodes.base import Line class RectFill(Node): r"""Add the filling of a Rect to the render tree Normally, this class isn't needed, because ``FilledRect`` combines ``RectLine`` with ``RectFill`` :param \**kwargs: See below :Keyword Arguments: * *start* (``Vector2D``) -- start edge of the rect fill * *end* (``Vector2D``) -- end edge of the rect fill * *layer* (``str``) -- layer on which the rect fill is drawn (default: 'F.SilkS') * *width* (``float``) -- width of the filling lines (default: 0.12) :Example: >>> from KicadModTree import * >>> RectFill(start=[-3, -2], end=[3, 2], layer='F.SilkS') """ def __init__(self, **kwargs): Node.__init__(self) self.start_pos = Vector2D(kwargs['start']) self.end_pos = Vector2D(kwargs['end']) self.layer = kwargs.get('layer', 'F.SilkS') self.width = kwargs.get('width', 0.12) # TODO: auto detection self.virtual_childs = self._createChildNodes(self.start_pos, self.end_pos, self.layer, self.width) def _createChildNodes(self, start_pos, end_pos, layer, width): nodes = [] cur_y_pos = min([start_pos.y, end_pos.y]) max_y_pos = max([start_pos.y, end_pos.y]) while (cur_y_pos + width) < max_y_pos: cur_y_pos += width new_node = Line(start=Vector2D(start_pos.x, cur_y_pos), end=Vector2D(end_pos.x, cur_y_pos), layer=layer, width=width) new_node._parent = self nodes.append(new_node) return nodes def getVirtualChilds(self): return self.virtual_childs def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_string = ['start: [x: {sx}, y: {sy}]'.format(sx=self.start_pos.x, sy=self.start_pos.y), 'end: [x: {ex}, y: {ey}]'.format(ex=self.end_pos.x, ey=self.end_pos.y)] render_text += " [{}]".format(", ".join(render_string)) return render_text ================================================ FILE: KicadModTree/nodes/specialized/RectLine.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node from .PolygoneLine import PolygoneLine class RectLine(PolygoneLine): r"""Add a Rect to the render tree :param \**kwargs: See below :Keyword Arguments: * *start* (``Vector2D``) -- start edge of the rect * *end* (``Vector2D``) -- end edge of the rect * *layer* (``str``) -- layer on which the rect is drawn * *width* (``float``) -- width of the outer line (default: None, which means auto detection) * *offset* (``Vector2D``, ``float``) -- offset of the rect line to the specified one :Example: >>> from KicadModTree import * >>> RectLine(start=[-3, -2], end=[3, 2], layer='F.SilkS') """ def __init__(self, **kwargs): self.start_pos = Vector2D(kwargs['start']) self.end_pos = Vector2D(kwargs['end']) # If specifed, an 'offset' can be applied to the RectLine. # For example, creating a border around a given Rect of a specified size if kwargs.get('offset'): # offset for the rect line # e.g. for creating a rectLine 0.5mm LARGER than the given rect, or similar offset = [0, 0] # Has an offset / inset been specified? if type(kwargs['offset']) in [int, float]: offset[0] = offset[1] = kwargs['offset'] elif type(kwargs['offset']) in [list, tuple] and len(kwargs['offset']) == 2: # Ensure that all offset params are numerical if all([type(i) in [int, float] for i in kwargs['offset']]): offset = kwargs['offset'] # For the offset to work properly, start-pos must be top-left, and end-pos must be bottom-right x1 = min(self.start_pos.x, self.end_pos.x) x2 = max(self.start_pos.x, self.end_pos.x) y1 = min(self.start_pos.y, self.end_pos.y) y2 = max(self.start_pos.y, self.end_pos.y) # Put the offset back in self.start_pos.x = x1 - offset[0] self.start_pos.y = y1 - offset[1] self.end_pos.x = x2 + offset[0] self.end_pos.y = y2 + offset[1] polygone_line = [{'x': self.start_pos.x, 'y': self.start_pos.y}, {'x': self.start_pos.x, 'y': self.end_pos.y}, {'x': self.end_pos.x, 'y': self.end_pos.y}, {'x': self.end_pos.x, 'y': self.start_pos.y}, {'x': self.start_pos.x, 'y': self.start_pos.y}] PolygoneLine.__init__(self, polygone=polygone_line, layer=kwargs['layer'], width=kwargs.get('width')) def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_text += " [start: [x: {sx}, y: {sy}] end: [x: {ex}, y: {ey}]]".format(sx=self.start_pos.x, sy=self.start_pos.y, ex=self.end_pos.x, ey=self.end_pos.y) return render_text ================================================ FILE: KicadModTree/nodes/specialized/RingPad.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr from __future__ import division from copy import copy from KicadModTree.nodes.Node import Node from KicadModTree.util.paramUtil import * from KicadModTree.util.geometric_util import geometricArc, geometricLine, BaseNodeIntersection from KicadModTree.Vector import * from KicadModTree.nodes.base.Pad import Pad from KicadModTree.nodes.base.Circle import Circle from KicadModTree.nodes.base.Arc import Arc from KicadModTree.nodes.base.Line import Line from math import sqrt, sin, cos, pi, ceil class RingPadPrimitive(Node): r"""Add a RingPad to the render tree :param \**kwargs: See below :Keyword Arguments: * *radius*: (``float``) -- middle radius of the ring * *width*: (``float``) -- width of the ring (outer radius - inner radius) * *at*: (``Vector2D``) -- position of the center * *layers*: (``Pad.Layers``) -- layers used for creating the pad * *number* (``int``, ``str``) -- number/name of the pad (default: \"\") """ def __init__(self, **kwargs): Node.__init__(self) self.at = Vector2D(kwargs.get('at', (0, 0))) self.radius = float(kwargs['radius']) self.width = float(kwargs['width']) self.layers = kwargs['layers'] self.number = kwargs.get('number', "") def copy(self): return RingPadPrimitive( at=self.at, radius=self.radius, width=self.width, layers=self.layers, number=self.number ) def getVirtualChilds(self): return [Pad(number=self.number, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=(self.at+Vector2D(self.radius, 0)), size=self.width, layers=self.layers, primitives=[Circle( center=(-self.radius, 0), radius=self.radius, width=self.width )] )] class ArcPadPrimitive(Node): r"""Add a RingPad to the render tree :param \**kwargs: See below :Keyword Arguments: * *number* (``int``, ``str``) -- number/name of the pad (default: \"\") * *width* (``float``) -- width of the pad * *layers* (``Pad.Layers``) -- layers on which are used for the pad * *round_radius_ratio* (``float``) -- round radius. default: 25\% of ring width * *max_round_radius* (``float``) -- maximum round radius, default: 0.25 Use none to ignore * *reference_arc* (``geometricArc``) -- the reference arc used for this pad * *start_line* (``geometricLine``) -- line confining the side near the reference points start point * *end_line* (``geometricLine``) -- line confining the side near the reference points end point * *minimum_overlap* (``float``) minimum overlap. default 0.1 """ def __init__(self, **kwargs): Node.__init__(self) self.reference_arc = geometricArc(geometry=kwargs['reference_arc']) self.width = float(kwargs['width']) self.number = kwargs.get('number', "") self.layers = kwargs['layers'] self.minimum_overlap = kwargs.get('minimum_overlap', 0.1) self.setRoundRadius(**kwargs) self.setLimitingLines(**kwargs) def setRoundRadius(self, **kwargs): if 'round_radius' in kwargs: self.round_radius = kwargs['round_radius'] return round_radius_ratio = kwargs.get('round_radius_ratio', 0.25) max_round_radius = kwargs.get('max_round_radius', 0.25) r = self.width*round_radius_ratio if max_round_radius is not None and max_round_radius > 0: self.round_radius = min(r, max_round_radius) def setLimitingLines(self, **kwargs): if kwargs.get('start_line') is not None: self.start_line = geometricLine(geometry=kwargs.get('start_line')) else: self.start_line = None if kwargs.get('end_line') is not None: self.end_line = geometricLine(geometry=kwargs.get('end_line')) else: self.end_line = None def copy(self): return ArcPadPrimitive( reference_arc=self.reference_arc, width=self.width, round_radius=self.round_radius, number=self.number, layers=self.layers, start_line=self.start_line, end_line=self.end_line, minimum_overlap=self.minimum_overlap ) def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.reference_arc.rotate(angle=angle, origin=origin, use_degrees=use_degrees) if self.start_line is not None: self.start_line.rotate(angle=angle, origin=origin, use_degrees=use_degrees) if self.end_line is not None: self.end_line.rotate(angle=angle, origin=origin, use_degrees=use_degrees) return self def translate(self, distance_vector): r""" Translate :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.reference_arc.translate(distance_vector) if self.start_line is not None: self.start_line.translate(distance_vector) if self.end_line is not None: self.end_line.translate(distance_vector) return self def _getStep(self): line_width = self.round_radius*2 if self.minimum_overlap >= line_width: raise ValueError('arc line width (round radius) too small for requested overlap') required_arcs = ceil((self.width-self.minimum_overlap) / (line_width-self.minimum_overlap)) return (self.width-line_width)/(required_arcs-1) def _getArcPrimitives(self): line_width = self.round_radius*2 step = self._getStep() r_inner = self.reference_arc.getRadius()-self.width/2+line_width/2 r_outer = self.reference_arc.getRadius()+self.width/2-line_width/2 ref_arc = Arc(geometry=self.reference_arc, width=line_width).setRadius(r_outer) nodes = [] r = r_inner while r < r_outer: nodes.append(ref_arc.copy().setRadius(r)) r += step nodes.append(ref_arc) if self.start_line is not None: nodes = self.__cutArcs(nodes, self.start_line, 1) if self.end_line is not None: nodes = self.__cutArcs(nodes, self.end_line, 0) nodes.append(Line(start=nodes[0].getEndPoint(), end=nodes[-1].getEndPoint(), width=line_width)) nodes.append(Line(start=nodes[0].getStartPoint(), end=nodes[-2].getStartPoint(), width=line_width)) return nodes def __cutArcs(self, arcs, line, index_to_keep): if line is None: return arcs result = [] for current_arc in arcs: try: result.append(current_arc.cut(line)[index_to_keep]) except IndexError as e: raise ValueError("Cutting the arc primitive with one of its endlines " + "did not result in the expected number of arcs.") return result def getVirtualChilds(self): at = self.reference_arc.getMidPoint() primitives = self._getArcPrimitives() for p in primitives: p.translate(-at) return [Pad( number=self.number, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=at, size=self.width/2, layers=self.layers, primitives=primitives )] class RingPad(Node): r"""Add a RingPad to the render tree :param \**kwargs: See below :Keyword Arguments: * *number* (``int``, ``str``) -- number/name of the pad (default: \"\") * *at* (``Vector2D``) -- center position of the pad * *rotation* (``float``) -- rotation of the pad * *inner_diameter* (``float``) -- diameter of the copper free inner zone * *size* (``float``) -- outside diameter of the pad * *num_anchors* (``int``) -- number of anchor pads around the circle * *num_paste_zones* (``int``) -- number of paste zones * *paste_to_paste_clearance* (``float``) -- clearance between two paste zones, needed only if number of paste zones > 1 default: 2*abs(solder_paste_margin) * *paste_round_radius_radio* (``float``) -- round over radius ratio. default 0.25 resulting radius must be larger than minimum overlap * *paste_max_round_radius* (``float``) -- maximum round radius. Only used if number of paste zones > 1 default: 0.25 set to None to ignore * *solder_paste_margin* (``float``) -- solder paste margin of the pad (default: 0) * *paste_outer_diameter* (``float``) -- together with paste inner diameter an alternative for defining the paste area * *paste_inner_diameter* (``float``) -- together with paste outer diameter an alternative for defining the paste area * *solder_mask_margin* (``float``) -- solder mask margin of the pad (default: 0) * *minimum_overlap* (``float``) -- minimum arc overlap. default 0.1 """ def __init__(self, **kwargs): Node.__init__(self) self.solder_mask_margin = kwargs.get('solder_mask_margin', 0) self.minimum_overlap = kwargs.get('minimum_overlap', 0.1) self._initPosition(**kwargs) self._initSize(**kwargs) self._initNumber(**kwargs) self._initPasteSettings(**kwargs) self._initNumAnchor(**kwargs) self._generatePads() def _initSize(self, **kwargs): _id = kwargs.get('inner_diameter') _od = kwargs.get('size') if _od is None or _id is None: raise KeyError('pad size or inside diameter not declared (like "size=1, inner_diameter=0.5")') if type(_id) not in [int, float] or type(_od) not in [int, float]: raise ValueError('ring pad size and inner_diameter only support int or float') if _id >= _od: raise ValueError('inner diameter must be larger than size') self.radius = (_id+_od)/4 self.width = (_od-_id)/2 self.size = _od self.is_circle = _id == 0 def _initNumber(self, **kwargs): self.number = kwargs.get('number', "") # default to an un-numbered pad def _initNumAnchor(self, **kwargs): self.num_anchor = int(kwargs.get('num_anchor', 1)) if self.num_anchor < 1: raise ValueError('num_anchor must be a positive integer') def _initPosition(self, **kwargs): if 'at' not in kwargs: raise KeyError('center position not declared (like "at=[0,0]")') self.at = Vector2D(kwargs.get('at')) def _initPasteSettings(self, **kwargs): self.solder_paste_margin = kwargs.get('solder_paste_margin', 0) if 'paste_outer_diameter' in kwargs and 'paste_inner_diameter' in kwargs: self.paste_width = (kwargs['paste_outer_diameter'] - kwargs['paste_inner_diameter'])/2 self.paste_center = (kwargs['paste_outer_diameter'] + kwargs['paste_inner_diameter'])/4 else: self.paste_width = self.width + 2*self.solder_paste_margin self.paste_center = self.radius self.num_paste_zones = int(kwargs.get('num_paste_zones', 1)) if self.num_paste_zones < 1: raise ValueError('num_paste_zones must be a positive integer') if self.num_paste_zones > 1: self.paste_max_round_radius = float(kwargs.get('paste_max_round_radius', 0.25)) self.paste_round_radius_radio = float( kwargs.get('paste_round_radius_radio', 0.25)) self.paste_to_paste_clearance = kwargs.get('paste_to_paste_clearance') if self.paste_to_paste_clearance is None: self.paste_to_paste_clearance = -self.solder_paste_margin if self.paste_round_radius_radio <= 0: raise ValueError('paste_round_radius_radio must be > 0') if self.paste_max_round_radius is not None and self.paste_max_round_radius <= 0: raise ValueError('paste_max_round_radius must be > 0') if self.paste_to_paste_clearance <= 0: raise ValueError('paste_to_paste_clearance must be > 0') def _generatePads(self): self.pads = [] if self.num_paste_zones > 1: layers = ['F.Cu', 'F.Mask'] self._generatePastePads() else: layers = ['F.Cu', 'F.Mask', 'F.Paste'] if not self.is_circle: self._generateCopperPads() else: self.pads.append( Pad(number=self.number, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CIRCLE, at=(self.at), size=self.size, layers=layers )) def _generatePastePads(self): ref_angle = 360/self.num_paste_zones ref_arc = geometricArc( center=self.at, start=self.at+(self.paste_center, 0), angle=ref_angle) pad = ArcPadPrimitive( number="", width=self.paste_width, round_radius_ratio=self.paste_round_radius_radio, max_round_radius=self.paste_max_round_radius, layers=['F.Paste'], reference_arc=ref_arc, minimum_overlap=self.minimum_overlap ) w = pad.round_radius*2 y = (self.paste_to_paste_clearance + w)/2 start_line = geometricLine(start=self.at+(0, y), end=self.at+(1, y)) end_line = geometricLine(start=self.at+(0, -y), end=self.at+(1, -y)).rotate(ref_angle, origin=self.at) if self.num_paste_zones == 2: end_line = None pad.setLimitingLines(start_line=start_line, end_line=end_line) self.pads.append(pad) for i in range(1, self.num_paste_zones): self.pads.append(pad.copy().rotate(i*ref_angle, origin=self.at)) def _generateMaskPads(self): w = self.width+2*self.solder_mask_margin self.pads.append( RingPadPrimitive( number="", at=self.at, width=self.width+2*self.solder_mask_margin, layers=['F.Mask'], radius=self.radius )) def _generateCopperPads(self): # kicad_mod.append(c) layers = ['F.Cu'] if self.num_paste_zones == 1: if self.solder_paste_margin == 0: layers.append('F.Paste') else: self.pads.append( RingPadPrimitive( number="", at=self.at, width=self.width+2*self.solder_paste_margin, layers=['F.Paste'], radius=self.radius )) if self.solder_mask_margin == 0: # bug in kicad so any clearance other than 0 needs a workaround layers.append('F.Mask') else: self._generateMaskPads() self.pads.append( RingPadPrimitive( number=self.number, at=self.at, width=self.width, layers=layers, radius=self.radius )) a = 360/self.num_anchor pos = Vector2D(self.radius, 0) for i in range(1, self.num_anchor): pos.rotate(a) self.pads.append(Pad(number=self.number, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CIRCLE, at=(self.at+pos), size=self.width-0.0001, layers=['F.Cu'], )) def getVirtualChilds(self): return self.pads ================================================ FILE: KicadModTree/nodes/specialized/Rotation.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import math from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node class Rotation(Node): """Apply rotation to the child tree :param r: angle which the child should rotate :type r: ``float`` :Example: >>> from KicadModTree import * >>> Rotation(90) """ def __init__(self, r): Node.__init__(self) self.rotation = r # in degree def getRealPosition(self, coordinate, rotation=None): if rotation is None: rotation = 0 parsed_coordinate = Vector2D(coordinate) phi = self.rotation*math.pi/180 rotation_coordinate = {'x': parsed_coordinate.x*math.cos(phi) + parsed_coordinate.y*math.sin(phi), 'y': -parsed_coordinate.x*math.sin(phi) + parsed_coordinate.y*math.cos(phi)} if not self._parent: if rotation is None: return rotation_coordinate else: return rotation_coordinate, rotation + self.rotation else: if rotation is None: rotation = 0 return self._parent.getRealPosition(rotation_coordinate, rotation + self.rotation) def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_text += " [r: {r}]".format(r=self.rotation) return render_text ================================================ FILE: KicadModTree/nodes/specialized/Translation.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from KicadModTree.Vector import * from KicadModTree.nodes.Node import Node class Translation(Node): """Apply translation to the child tree :param x: change of x coordinate :type x: ``float`` :param y: change of y coordinate :type y: ``float`` :Example: >>> from KicadModTree import * >>> Translation(1, 2) """ def __init__(self, x, y): Node.__init__(self) # translation information self.offset_x = x self.offset_y = y def getRealPosition(self, coordinate, rotation=None): parsed_coordinate = Vector2D(coordinate) # calculate translation translation_coordinate = {'x': parsed_coordinate.x + self.offset_x, 'y': parsed_coordinate.y + self.offset_y} if not self._parent: if rotation is None: return translation_coordinate else: return translation_coordinate, rotation else: return self._parent.getRealPosition(translation_coordinate, rotation) def _getRenderTreeText(self): render_text = Node._getRenderTreeText(self) render_text += " [x: {x}, y: {y}]".format(x=self.offset_x, y=self.offset_y) return render_text ================================================ FILE: KicadModTree/nodes/specialized/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from .Translation import Translation from .Rotation import Rotation from .PolygoneLine import PolygoneLine from .RectLine import RectLine from .RectFill import RectFill from .FilledRect import FilledRect from .PadArray import PadArray from .ExposedPad import ExposedPad from .ChamferedPad import ChamferedPad, CornerSelection from .ChamferedPadGrid import * from .RingPad import RingPad ================================================ FILE: KicadModTree/tests/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, ================================================ FILE: KicadModTree/tests/datatypes/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, from .test_Vector2D import Vector2DTests from .test_Vector3D import Vector3DTests ================================================ FILE: KicadModTree/tests/datatypes/test_Vector2D.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2018 by Thomas Pointhuber, import unittest import math from KicadModTree.Vector import * class Vector2DTests(unittest.TestCase): def test_init(self): p1 = Vector2D([1, 2]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) p2 = Vector2D((4, 5)) self.assertEqual(p2.x, 4) self.assertEqual(p2.y, 5) p3 = Vector2D({'x': 7, 'y': 8}) self.assertEqual(p3.x, 7) self.assertEqual(p3.y, 8) p3_empty = Vector2D({}) self.assertEqual(p3_empty.x, 0) self.assertEqual(p3_empty.y, 0) p4 = Vector2D(p1) self.assertEqual(p4.x, 1) self.assertEqual(p4.y, 2) p5 = Vector2D(1, 2) self.assertEqual(p5.x, 1) self.assertEqual(p5.y, 2) # TODO: test float datatype # TODO: invalid type tests # TODO: tests if int is always converted to float def test_round_to(self): p1 = Vector2D([1.234, 5.678]).round_to(0) self.assertAlmostEqual(p1.x, 1.234) self.assertAlmostEqual(p1.y, 5.678) p2 = Vector2D([1.234, 5.678]).round_to(0.1) self.assertAlmostEqual(p2.x, 1.2) self.assertAlmostEqual(p2.y, 5.7) p3 = Vector2D([1.234, 5.678]).round_to(0.01) self.assertAlmostEqual(p3.x, 1.23) self.assertAlmostEqual(p3.y, 5.68) p4 = Vector2D([1.234, 5.678]).round_to(0.001) self.assertAlmostEqual(p4.x, 1.234) self.assertAlmostEqual(p4.y, 5.678) p5 = Vector2D([1.234, 5.678]).round_to(0.0001) self.assertAlmostEqual(p5.x, 1.234) self.assertAlmostEqual(p5.y, 5.678) def test_add(self): p1 = Vector2D([1, 2]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) p2 = p1 + 5 self.assertEqual(p2.x, 6) self.assertEqual(p2.y, 7) p3 = p1 + (-5) self.assertEqual(p3.x, -4) self.assertEqual(p3.y, -3) p4 = p1 + [4, 2] self.assertEqual(p4.x, 5) self.assertEqual(p4.y, 4) p5 = p1 + [-5, -3] self.assertEqual(p5.x, -4) self.assertEqual(p5.y, -1) # TODO: invalid type tests def test_sub(self): p1 = Vector2D([1, 2]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) p2 = p1 - 5 self.assertEqual(p2.x, -4) self.assertEqual(p2.y, -3) p3 = p1 - (-5) self.assertEqual(p3.x, 6) self.assertEqual(p3.y, 7) p4 = p1 - [4, 2] self.assertEqual(p4.x, -3) self.assertEqual(p4.y, 0) p5 = p1 - [-5, -3] self.assertEqual(p5.x, 6) self.assertEqual(p5.y, 5) # TODO: invalid type tests def test_mul(self): p1 = Vector2D([1, 2]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) p2 = p1 * 5 self.assertEqual(p2.x, 5) self.assertEqual(p2.y, 10) p3 = p1 * (-5) self.assertEqual(p3.x, -5) self.assertEqual(p3.y, -10) p4 = p1 * [4, 5] self.assertEqual(p4.x, 4) self.assertEqual(p4.y, 10) p5 = p1 * [-5, -3] self.assertEqual(p5.x, -5) self.assertEqual(p5.y, -6) # TODO: invalid type tests def test_div(self): p1 = Vector2D([1, 2]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) p2 = p1 / 5 self.assertEqual(p2.x, 0.2) self.assertEqual(p2.y, 0.4) p3 = p1 / (-5) self.assertEqual(p3.x, -0.2) self.assertEqual(p3.y, -0.4) p4 = p1 / [4, 5] self.assertEqual(p4.x, 0.25) self.assertEqual(p4.y, 0.4) p5 = p1 / [-5, -2] self.assertEqual(p5.x, -0.2) self.assertEqual(p5.y, -1) # TODO: division by zero tests # TODO: invalid type tests def test_polar(self): p1 = Vector2D.from_polar(math.sqrt(2), 45, use_degrees=True) self.assertAlmostEqual(p1.x, 1) self.assertAlmostEqual(p1.y, 1) p1 = Vector2D.from_polar(2, -90, use_degrees=True, origin=(6, 1)) self.assertAlmostEqual(p1.x, 6) self.assertAlmostEqual(p1.y, -1) r, a = p1.to_polar(use_degrees=True, origin=(6, 1)) self.assertAlmostEqual(r, 2) self.assertAlmostEqual(a, -90) p1.rotate(90, use_degrees=True, origin=(6, 1)) self.assertAlmostEqual(p1.x, 8) self.assertAlmostEqual(p1.y, 1) p1 = Vector2D.from_polar(math.sqrt(2), 135, use_degrees=True) self.assertAlmostEqual(p1.x, -1) self.assertAlmostEqual(p1.y, 1) p1.rotate(90, use_degrees=True) self.assertAlmostEqual(p1.x, -1) self.assertAlmostEqual(p1.y, -1) r, a = p1.to_polar(use_degrees=True) self.assertAlmostEqual(r, math.sqrt(2)) self.assertAlmostEqual(a, -135) ================================================ FILE: KicadModTree/tests/datatypes/test_Vector3D.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, import unittest from KicadModTree.Vector import * class Vector3DTests(unittest.TestCase): def test_init(self): p1 = Vector3D([1, 2, 3]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) self.assertEqual(p1.z, 3) p1_xy = Vector3D([1, 2]) self.assertEqual(p1_xy.x, 1) self.assertEqual(p1_xy.y, 2) self.assertEqual(p1_xy.z, 0) p2 = Vector3D((4, 5, 6)) self.assertEqual(p2.x, 4) self.assertEqual(p2.y, 5) self.assertEqual(p2.z, 6) p2_xy = Vector3D((4, 5)) self.assertEqual(p2_xy.x, 4) self.assertEqual(p2_xy.y, 5) self.assertEqual(p2_xy.z, 0) p3 = Vector3D({'x': 7, 'y': 8, 'z': 9}) self.assertEqual(p3.x, 7) self.assertEqual(p3.y, 8) self.assertEqual(p3.z, 9) p3_xy = Vector3D({'x': 7, 'y': 8}) self.assertEqual(p3_xy.x, 7) self.assertEqual(p3_xy.y, 8) self.assertEqual(p3_xy.z, 0) p3_empty = Vector3D({}) self.assertEqual(p3_empty.x, 0) self.assertEqual(p3_empty.y, 0) self.assertEqual(p3_empty.z, 0) p4 = Vector3D(p1) self.assertEqual(p4.x, 1) self.assertEqual(p4.y, 2) self.assertEqual(p4.z, 3) p5 = Vector3D(1, 2, 3) self.assertEqual(p5.x, 1) self.assertEqual(p5.y, 2) self.assertEqual(p5.z, 3) p5_xy = Vector3D(1, 2) self.assertEqual(p5_xy.x, 1) self.assertEqual(p5_xy.y, 2) self.assertEqual(p5_xy.z, 0) # TODO: test float datatype # TODO: invalid type tests # TODO: tests if int is always converted to float def test_round_to(self): p1 = Vector3D([1.234, 5.678, 9.012]).round_to(0) self.assertAlmostEqual(p1.x, 1.234) self.assertAlmostEqual(p1.y, 5.678) self.assertAlmostEqual(p1.z, 9.012) p2 = Vector3D([1.234, 5.678, 9.012]).round_to(0.1) self.assertAlmostEqual(p2.x, 1.2) self.assertAlmostEqual(p2.y, 5.7) self.assertAlmostEqual(p2.z, 9) p3 = Vector3D([1.234, 5.678, 9.012]).round_to(0.01) self.assertAlmostEqual(p3.x, 1.23) self.assertAlmostEqual(p3.y, 5.68) self.assertAlmostEqual(p3.z, 9.01) p4 = Vector3D([1.234, 5.678, 9.012]).round_to(0.001) self.assertAlmostEqual(p4.x, 1.234) self.assertAlmostEqual(p4.y, 5.678) self.assertAlmostEqual(p4.z, 9.012) p5 = Vector3D([1.234, 5.678, 9.012]).round_to(0.0001) self.assertAlmostEqual(p5.x, 1.234) self.assertAlmostEqual(p5.y, 5.678) self.assertAlmostEqual(p5.z, 9.012) def test_add(self): p1 = Vector3D([1, 2, 3]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) self.assertEqual(p1.z, 3) p2 = p1 + 5 self.assertEqual(p2.x, 6) self.assertEqual(p2.y, 7) self.assertEqual(p2.z, 8) p3 = p1 + (-5) self.assertEqual(p3.x, -4) self.assertEqual(p3.y, -3) self.assertEqual(p3.z, -2) p4 = p1 + [4, 2, -2] self.assertEqual(p4.x, 5) self.assertEqual(p4.y, 4) self.assertEqual(p4.z, 1) p5 = p1 + [-5, -3] self.assertEqual(p5.x, -4) self.assertEqual(p5.y, -1) self.assertEqual(p5.z, 3) # TODO: invalid type tests def test_sub(self): p1 = Vector3D([1, 2, 3]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) self.assertEqual(p1.z, 3) p2 = p1 - 5 self.assertEqual(p2.x, -4) self.assertEqual(p2.y, -3) self.assertEqual(p2.z, -2) p3 = p1 - (-5) self.assertEqual(p3.x, 6) self.assertEqual(p3.y, 7) self.assertEqual(p3.z, 8) p4 = p1 - [4, 2, -2] self.assertEqual(p4.x, -3) self.assertEqual(p4.y, 0) self.assertEqual(p4.z, 5) p5 = p1 - [-5, -3] self.assertEqual(p5.x, 6) self.assertEqual(p5.y, 5) self.assertEqual(p5.z, 3) # TODO: invalid type tests def test_mul(self): p1 = Vector3D([1, 2, 3]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) self.assertEqual(p1.z, 3) p2 = p1 * 5 self.assertEqual(p2.x, 5) self.assertEqual(p2.y, 10) self.assertEqual(p2.z, 15) p3 = p1 * (-5) self.assertEqual(p3.x, -5) self.assertEqual(p3.y, -10) self.assertEqual(p3.z, -15) p4 = p1 * [4, 5, -2] self.assertEqual(p4.x, 4) self.assertEqual(p4.y, 10) self.assertEqual(p4.z, -6) p5 = p1 * [-5, -3] self.assertEqual(p5.x, -5) self.assertEqual(p5.y, -6) self.assertEqual(p5.z, 0) # TODO: invalid type tests def test_div(self): p1 = Vector3D([1, 2, 3]) self.assertEqual(p1.x, 1) self.assertEqual(p1.y, 2) self.assertEqual(p1.z, 3) p2 = p1 / 5 self.assertEqual(p2.x, 0.2) self.assertEqual(p2.y, 0.4) self.assertEqual(p2.z, 0.6) p3 = p1 / (-5) self.assertEqual(p3.x, -0.2) self.assertEqual(p3.y, -0.4) self.assertEqual(p3.z, -0.6) p4 = p1 / [4, 5, -2] self.assertEqual(p4.x, 0.25) self.assertEqual(p4.y, 0.4) self.assertEqual(p4.z, -1.5) # TODO: division by zero tests # TODO: invalid type tests ================================================ FILE: KicadModTree/tests/moduletests/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2018 by Thomas Pointhuber, from .test_simple_footprints import SimpleFootprintTests from .test_kicad5_padshapes import Kicad5PadsTests from .test_exposed_pad import ExposedPadTests from .test_arc import ArcTests from .test_rotation import RotationTests ================================================ FILE: KicadModTree/tests/moduletests/test_arc.py ================================================ import unittest import math from KicadModTree import * RESULT_kx90DEG = """(module test (layer F.Cu) (tedit 0) (fp_arc (start 0 0) (end 1 0) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 -1.2) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -1.4 0) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 1.6) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 2 0) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 2.2) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -2.4 0) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 -2.6) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 3 0) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 -3.2) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -3.4 0) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 3.6) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 4 0) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 4.2) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -4.4 0) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 -4.6) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 5 0) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 -5.2) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -5.4 0) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 0 5.6) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 6 0) (angle -180) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -6.2 0) (angle -180) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 6.6 0) (angle 180) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -6.8 0) (angle 180) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 4.949747 -4.949747) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -5.091169 -5.091169) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -5.23259 5.23259) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 5.374012 5.374012) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 5.656854 5.656854) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end 5.798276 -5.798276) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -5.939697 -5.939697) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start 0 0) (end -6.081118 6.081118) (angle -90) (layer F.SilkS) (width 0.12)) )""" RESULT_kx90DEG_45deg = """(module test (layer F.Cu) (tedit 0) (fp_arc (start -5 5) (end -4.292893 5.707107) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -4.151472 4.151472) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -5.989949 4.010051) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -6.131371 6.131371) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -3.585786 6.414214) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -6.555635 6.555635) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -6.697056 3.302944) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -3.161522 3.161522) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -2.87868 7.12132) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -2.737258 2.737258) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -7.404163 2.595837) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -7.545584 7.545584) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -2.171573 7.828427) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -7.969848 7.969848) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -8.11127 1.88873) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -1.747309 1.747309) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -1.464466 8.535534) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -1.323045 1.323045) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -8.818377 1.181623) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -8.959798 8.959798) (angle 270) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -0.757359 9.242641) (angle -180) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -9.384062 0.615938) (angle -180) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -0.333095 9.666905) (angle 180) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -9.808326 0.191674) (angle 180) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end 2 5) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -5 -2.2) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -12.4 5) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -5 12.6) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -5 13) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end 3.2 5) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -5 -3.4) (angle -90) (layer F.SilkS) (width 0.12)) (fp_arc (start -5 5) (end -13.6 5) (angle -90) (layer F.SilkS) (width 0.12)) )""" class ArcTests(unittest.TestCase): def testArcsKx90deg(self): kicad_mod = Footprint("test") center = Vector2D(0, 0) kicad_mod.append( Arc(center=center, start=Vector2D(1, 0), angle=-90)) kicad_mod.append( Arc(center=center, start=Vector2D(0, -1.2), angle=-90)) kicad_mod.append( Arc(center=center, start=Vector2D(-1.4, 0), angle=-90)) kicad_mod.append( Arc(center=center, start=Vector2D(0, 1.6), angle=-90)) kicad_mod.append( Arc(center=center, start=Vector2D(2, 0), angle=90)) kicad_mod.append( Arc(center=center, start=Vector2D(0, 2.2), angle=90)) kicad_mod.append( Arc(center=center, start=Vector2D(-2.4, 0), angle=90)) kicad_mod.append( Arc(center=center, start=Vector2D(0, -2.6), angle=90)) kicad_mod.append( Arc(center=center, start=Vector2D(3, 0), end=Vector2D(0, -3))) kicad_mod.append( Arc(center=center, start=Vector2D(0, -3.2), end=Vector2D(-3.2, 0))) kicad_mod.append( Arc(center=center, start=Vector2D(-3.4, 0), end=Vector2D(0, 3.4))) kicad_mod.append( Arc(center=center, start=Vector2D(0, 3.6), end=Vector2D(3.6, 0))) kicad_mod.append( Arc(center=center, start=Vector2D(4, 0), end=Vector2D(0, 4))) kicad_mod.append( Arc(center=center, start=Vector2D(0, 4.2), end=Vector2D(-4.2, 0))) kicad_mod.append( Arc(center=center, start=Vector2D(-4.4, 0), end=Vector2D(0, -4.4))) kicad_mod.append( Arc(center=center, start=Vector2D(0, -4.6), end=Vector2D(4.6, 0))) kicad_mod.append( Arc(center=center, start=Vector2D(5, 0), end=Vector2D(0, -5), long_way=True)) kicad_mod.append( Arc(center=center, start=Vector2D(0, -5.2), end=Vector2D(-5.2, 0), long_way=True)) kicad_mod.append( Arc(center=center, start=Vector2D(-5.4, 0), end=Vector2D(0, 5.4), long_way=True)) kicad_mod.append( Arc(center=center, start=Vector2D(0, 5.6), end=Vector2D(5.6, 0), long_way=True)) kicad_mod.append( Arc(center=center, start=Vector2D(6, 0), end=Vector2D(-6, 0))) kicad_mod.append( Arc(center=center, start=Vector2D(-6.2, 0), end=Vector2D(6.2, 0))) kicad_mod.append( Arc(center=center, start=Vector2D(6.6, 0), end=Vector2D(-6.6, 0), long_way=True)) kicad_mod.append( Arc(center=center, start=Vector2D(-6.8, 0), end=Vector2D(6.8, 0), long_way=True)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(7, 0), angle=90)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(0, -7.2), angle=90)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(-7.4, 0), angle=90)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(0, 7.6), angle=90)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(8, 0), angle=-90)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(0, -8.2), angle=-90)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(-8.4, 0), angle=-90)) kicad_mod.append( Arc(center=center, midpoint=Vector2D(0, 8.6), angle=-90)) file_handler = KicadFileHandler(kicad_mod) self.assertEqual(file_handler.serialize(timestamp=0), RESULT_kx90DEG) # file_handler.writeFile('test_arc4.kicad_mod') def testArcsKx90degOffsetRotated(self): kicad_mod = Footprint("test") center = Vector2D(-5, 5) kicad_mod.append( Arc( center=center, start=(Vector2D(1, 0)+center).rotate(45, origin=center), angle=-90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, -1.2)+center).rotate(45, origin=center), angle=-90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(-1.4, 0)+center).rotate(45, origin=center), angle=-90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, 1.6)+center).rotate(45, origin=center), angle=-90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(2, 0)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, 2.2)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(-2.4, 0)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, -2.6)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, start=(Vector2D(3, 0)+center).rotate(45, origin=center), end=(Vector2D(0, -3)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, -3.2)+center).rotate(45, origin=center), end=(Vector2D(-3.2, 0)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(-3.4, 0)+center).rotate(45, origin=center), end=(Vector2D(0, 3.4)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, 3.6)+center).rotate(45, origin=center), end=(Vector2D(3.6, 0)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(4, 0)+center).rotate(45, origin=center), end=(Vector2D(0, 4)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, 4.2)+center).rotate(45, origin=center), end=(Vector2D(-4.2, 0)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(-4.4, 0)+center).rotate(45, origin=center), end=(Vector2D(0, -4.4)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, -4.6)+center).rotate(45, origin=center), end=(Vector2D(4.6, 0)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(5, 0)+center).rotate(45, origin=center), end=(Vector2D(0, -5)+center).rotate(45, origin=center), long_way=True )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, -5.2)+center).rotate(45, origin=center), end=(Vector2D(-5.2, 0)+center).rotate(45, origin=center), long_way=True )) kicad_mod.append( Arc( center=center, start=(Vector2D(-5.4, 0)+center).rotate(45, origin=center), end=(Vector2D(0, 5.4)+center).rotate(45, origin=center), long_way=True )) kicad_mod.append( Arc( center=center, start=(Vector2D(0, 5.6)+center).rotate(45, origin=center), end=(Vector2D(5.6, 0)+center).rotate(45, origin=center), long_way=True )) kicad_mod.append( Arc( center=center, start=(Vector2D(6, 0)+center).rotate(45, origin=center), end=(Vector2D(-6, 0)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(-6.2, 0)+center).rotate(45, origin=center), end=(Vector2D(6.2, 0)+center).rotate(45, origin=center) )) kicad_mod.append( Arc( center=center, start=(Vector2D(6.6, 0)+center).rotate(45, origin=center), end=(Vector2D(-6.6, 0)+center).rotate(45, origin=center), long_way=True )) kicad_mod.append( Arc( center=center, start=(Vector2D(-6.8, 0)+center).rotate(45, origin=center), end=(Vector2D(6.8, 0)+center).rotate(45, origin=center), long_way=True )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(7, 0)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(0, -7.2)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(-7.4, 0)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(0, 7.6)+center).rotate(45, origin=center), angle=90 )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(8, 0)+center).rotate(45, origin=center), angle=-90 )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(0, -8.2)+center).rotate(45, origin=center), angle=-90 )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(-8.4, 0)+center).rotate(45, origin=center), angle=-90 )) kicad_mod.append( Arc( center=center, midpoint=(Vector2D(0, 8.6)+center).rotate(45, origin=center), angle=-90 )) file_handler = KicadFileHandler(kicad_mod) self.assertEqual(file_handler.serialize(timestamp=0), RESULT_kx90DEG_45deg) # file_handler.writeFile('test_arc5.kicad_mod') ================================================ FILE: KicadModTree/tests/moduletests/test_exposed_pad.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2018 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr import unittest from KicadModTree import * RESULT_SIMPLE_EP_FP = """(module simple_exposed (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value simple_exposed (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad "" smd rect (at 0 1) (size 2.1 2.1) (layers F.Mask)) (pad 3 smd rect (at 0 1) (size 2.1 3) (layers F.Cu)) (pad 3 thru_hole circle (at -0.75 -0.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 -0.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.75 -0.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.75 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.75 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 1) (size 2.1 3) (layers B.Cu)) (pad "" smd rect (at -0.525 0.3) (size 0.85 0.56) (layers F.Paste)) (pad "" smd rect (at -0.525 1) (size 0.85 0.56) (layers F.Paste)) (pad "" smd rect (at -0.525 1.7) (size 0.85 0.56) (layers F.Paste)) (pad "" smd rect (at 0.525 0.3) (size 0.85 0.56) (layers F.Paste)) (pad "" smd rect (at 0.525 1) (size 0.85 0.56) (layers F.Paste)) (pad "" smd rect (at 0.525 1.7) (size 0.85 0.56) (layers F.Paste)) )""" RESULT_SIMPLE_EP_NO_ROUNDING_FP = """(module simple_exposed (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value simple_exposed (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad "" smd rect (at 0 1) (size 2.1 2.1) (layers F.Mask)) (pad 3 smd rect (at 0 1) (size 2.1 3) (layers F.Cu)) (pad 3 thru_hole circle (at -0.75 -0.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 -0.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.75 -0.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.75 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.75 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 1) (size 2.1 3) (layers B.Cu)) (pad "" smd rect (at -0.525 0.3) (size 0.846537 0.564358) (layers F.Paste)) (pad "" smd rect (at -0.525 1) (size 0.846537 0.564358) (layers F.Paste)) (pad "" smd rect (at -0.525 1.7) (size 0.846537 0.564358) (layers F.Paste)) (pad "" smd rect (at 0.525 0.3) (size 0.846537 0.564358) (layers F.Paste)) (pad "" smd rect (at 0.525 1) (size 0.846537 0.564358) (layers F.Paste)) (pad "" smd rect (at 0.525 1.7) (size 0.846537 0.564358) (layers F.Paste)) )""" RESULT_MINIMAL_EP_SPECIFICATION = """(module simple_exposed (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value simple_exposed (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at 0 0) (size 2.1 3) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at -0.75 -1.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 -1.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.75 -1.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.75 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.75 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.75 1.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 1.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.75 1.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 0) (size 2.1 3) (layers B.Cu)) (pad "" smd rect (at -0.525 -0.75) (size 0.85 1.21) (layers F.Paste)) (pad "" smd rect (at -0.525 0.75) (size 0.85 1.21) (layers F.Paste)) (pad "" smd rect (at 0.525 -0.75) (size 0.85 1.21) (layers F.Paste)) (pad "" smd rect (at 0.525 0.75) (size 0.85 1.21) (layers F.Paste)) )""" RESULT_EP_PASTE_GEN_INNER = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at 0 0) (size 5 5) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at -2.2 -2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 2.2 -2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -2.2 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 2.2 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 0) (size 5 5) (layers B.Cu)) (pad "" smd custom (at -1.466667 -1.466667) (size 1.230653 1.230653) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.671855 -0.511969) (xy -0.511969 -0.671855) (xy 0.671855 -0.671855) (xy 0.671855 0.671855) (xy -0.671855 0.671855)) (width 0)) )) (pad "" smd rect (at -1.466667 0) (size 1.34371 1.34371) (layers F.Paste)) (pad "" smd custom (at -1.466667 1.466667) (size 1.230653 1.230653) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.671855 -0.671855) (xy 0.671855 -0.671855) (xy 0.671855 0.671855) (xy -0.511969 0.671855) (xy -0.671855 0.511969)) (width 0)) )) (pad "" smd rect (at 0 -1.466667) (size 1.34371 1.34371) (layers F.Paste)) (pad "" smd rect (at 0 0) (size 1.34371 1.34371) (layers F.Paste)) (pad "" smd rect (at 0 1.466667) (size 1.34371 1.34371) (layers F.Paste)) (pad "" smd custom (at 1.466667 -1.466667) (size 1.230653 1.230653) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.671855 -0.671855) (xy 0.511969 -0.671855) (xy 0.671855 -0.511969) (xy 0.671855 0.671855) (xy -0.671855 0.671855)) (width 0)) )) (pad "" smd rect (at 1.466667 0) (size 1.34371 1.34371) (layers F.Paste)) (pad "" smd custom (at 1.466667 1.466667) (size 1.230653 1.230653) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.671855 -0.671855) (xy 0.671855 -0.671855) (xy 0.671855 0.511969) (xy 0.511969 0.671855) (xy -0.671855 0.671855)) (width 0)) )) )""" RESULT_EP_PASTE_GEN_INNER2 = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at 0 0) (size 5 5) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at -2.2 -2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.733333 -2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.733333 -2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 2.2 -2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -2.2 -0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.733333 -0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.733333 -0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 2.2 -0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -2.2 0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.733333 0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.733333 0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 2.2 0.733333) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -2.2 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -0.733333 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0.733333 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 2.2 2.2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 0) (size 5 5) (layers B.Cu)) (pad "" smd custom (at -1.833333 -1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.833333 -1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at -1.1 -1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.1 -1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.833333 -0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.833333 0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at -1.1 -0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.1 0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.833333 1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.833333 1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at -1.1 1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -1.1 1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -0.366667 -1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -0.366667 -1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at 0.366667 -1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 0.366667 -1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -0.366667 -0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -0.366667 0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at 0.366667 -0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 0.366667 0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -0.366667 1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at -0.366667 1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at 0.366667 1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 0.366667 1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.1 -1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.1 -1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at 1.833333 -1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.833333 -1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.1 -0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.1 0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at 1.833333 -0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.833333 0.366667) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.1 1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.155863) (xy -0.155863 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.1 1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.294628) (xy -0.155863 0.294628) (xy -0.294628 0.155863)) (width 0)) )) (pad "" smd custom (at 1.833333 1.1) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.155863 -0.294628) (xy 0.294628 -0.155863) (xy 0.294628 0.294628) (xy -0.294628 0.294628)) (width 0)) )) (pad "" smd custom (at 1.833333 1.833333) (size 0.491134 0.491134) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.294628 -0.294628) (xy 0.294628 -0.294628) (xy 0.294628 0.155863) (xy 0.155863 0.294628) (xy -0.294628 0.294628)) (width 0)) )) )""" RESULT_EP_PASTE_GEN_INNER_AND_OUTHER = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at 7 5) (size 12 8) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at 4 3) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 7 3) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 10 3) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 4 5) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 7 5) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 10 5) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 4 7) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 7 7) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 10 7) (size 0.8 0.8) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 7 5) (size 6.8 4.8) (layers B.Cu)) (pad "" smd custom (at 4.75 3.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 4.75 4.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd custom (at 6.25 3.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 6.25 4.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 4.75 5.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 4.75 6.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd custom (at 6.25 5.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 6.25 6.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 7.75 3.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 7.75 4.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd custom (at 9.25 3.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 9.25 4.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 7.75 5.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 7.75 6.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd custom (at 9.25 5.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 9.25 6.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 1.75 3.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 1.75 4.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 3.25 3.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 3.25 4.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 1.75 5.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 1.75 6.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 3.25 5.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 3.25 6.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 10.75 3.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 10.75 4.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd rect (at 12.25 3.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 12.25 4.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 10.75 5.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 10.75 6.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd rect (at 12.25 5.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 12.25 6.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 4.75 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 4.75 2.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd rect (at 6.25 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 6.25 2.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 7.75 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 7.75 2.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd rect (at 9.25 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 9.25 2.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd custom (at 4.75 7.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 4.75 8.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 6.25 7.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 6.25 8.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 7.75 7.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 7.75 8.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 9.25 7.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 9.25 8.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 1.75 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 1.75 2.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 3.25 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 3.25 2.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.05682) (xy 0.265985 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 1.75 7.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 1.75 8.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 3.25 7.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.265985 -0.41833) (xy 0.627495 -0.05682) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 3.25 8.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 10.75 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 10.75 2.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.265985 0.41833) (xy -0.627495 0.05682)) (width 0)) )) (pad "" smd rect (at 12.25 1.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 12.25 2.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd custom (at 10.75 7.5) (size 0.581034 0.581034) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.627495 -0.05682) (xy -0.265985 -0.41833) (xy 0.627495 -0.41833) (xy 0.627495 0.41833) (xy -0.627495 0.41833)) (width 0)) )) (pad "" smd rect (at 10.75 8.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 12.25 7.5) (size 1.25499 0.83666) (layers F.Paste)) (pad "" smd rect (at 12.25 8.5) (size 1.25499 0.83666) (layers F.Paste)) )""" RESULT_EP_PASTE_GEN_INNER_ONLY_Y_AND_OUTHER = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at 0 0) (size 3 5) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at 0 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 0) (size 0.6 4.6) (layers B.Cu)) (pad "" smd rect (at -1.125 -1.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd rect (at -1.125 -0.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd custom (at -0.375 -1.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.403113) (xy 0.047623 -0.403113) (xy 0.302335 -0.148401) (xy 0.302335 0.403113) (xy -0.302335 0.403113)) (width 0)) )) (pad "" smd custom (at -0.375 -0.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.403113) (xy 0.302335 -0.403113) (xy 0.302335 0.148401) (xy 0.047623 0.403113) (xy -0.302335 0.403113)) (width 0)) )) (pad "" smd rect (at -1.125 0.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd rect (at -1.125 1.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd custom (at -0.375 0.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.403113) (xy 0.047623 -0.403113) (xy 0.302335 -0.148401) (xy 0.302335 0.403113) (xy -0.302335 0.403113)) (width 0)) )) (pad "" smd custom (at -0.375 1.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.403113) (xy 0.302335 -0.403113) (xy 0.302335 0.148401) (xy 0.047623 0.403113) (xy -0.302335 0.403113)) (width 0)) )) (pad "" smd custom (at 0.375 -1.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.148401) (xy -0.047623 -0.403113) (xy 0.302335 -0.403113) (xy 0.302335 0.403113) (xy -0.302335 0.403113)) (width 0)) )) (pad "" smd custom (at 0.375 -0.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.403113) (xy 0.302335 -0.403113) (xy 0.302335 0.403113) (xy -0.047623 0.403113) (xy -0.302335 0.148401)) (width 0)) )) (pad "" smd rect (at 1.125 -1.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd rect (at 1.125 -0.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd custom (at 0.375 0.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.148401) (xy -0.047623 -0.403113) (xy 0.302335 -0.403113) (xy 0.302335 0.403113) (xy -0.302335 0.403113)) (width 0)) )) (pad "" smd custom (at 0.375 1.5) (size 0.424561 0.424561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.403113) (xy 0.302335 -0.403113) (xy 0.302335 0.403113) (xy -0.047623 0.403113) (xy -0.302335 0.148401)) (width 0)) )) (pad "" smd rect (at 1.125 0.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd rect (at 1.125 1.5) (size 0.604669 0.806226) (layers F.Paste)) (pad "" smd rect (at -1.125 -2.25) (size 0.604669 0.403113) (layers F.Paste)) (pad "" smd custom (at -0.375 -2.25) (size 0.18875 0.18875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.201556) (xy 0.302335 -0.201556) (xy 0.302335 -0.101599) (xy -0.000821 0.201556) (xy -0.302335 0.201556)) (width 0)) )) (pad "" smd rect (at -1.125 2.25) (size 0.604669 0.403113) (layers F.Paste)) (pad "" smd custom (at -0.375 2.25) (size 0.18875 0.18875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.201556) (xy -0.000821 -0.201556) (xy 0.302335 0.101599) (xy 0.302335 0.201556) (xy -0.302335 0.201556)) (width 0)) )) (pad "" smd custom (at 0.375 -2.25) (size 0.18875 0.18875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 -0.201556) (xy 0.302335 -0.201556) (xy 0.302335 0.201556) (xy 0.000821 0.201556) (xy -0.302335 -0.101599)) (width 0)) )) (pad "" smd rect (at 1.125 -2.25) (size 0.604669 0.403113) (layers F.Paste)) (pad "" smd custom (at 0.375 2.25) (size 0.18875 0.18875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.302335 0.101599) (xy 0.000821 -0.201556) (xy 0.302335 -0.201556) (xy 0.302335 0.201556) (xy -0.302335 0.201556)) (width 0)) )) (pad "" smd rect (at 1.125 2.25) (size 0.604669 0.403113) (layers F.Paste)) )""" RESULT_EP_PASTE_GEN_INNER_ONLY_X_AND_OUTHER = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at 0 0) (size 4 3) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at -1 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 1 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 0) (size 2.6 0.6) (layers B.Cu)) (pad "" smd rect (at -0.75 -1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd custom (at -0.75 -0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.302335) (xy 0.201556 -0.302335) (xy 0.201556 0.302335) (xy -0.110533 0.302335) (xy -0.201556 0.211312)) (width 0)) )) (pad "" smd rect (at -0.25 -1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd custom (at -0.25 -0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.302335) (xy 0.201556 -0.302335) (xy 0.201556 0.211312) (xy 0.110533 0.302335) (xy -0.201556 0.302335)) (width 0)) )) (pad "" smd rect (at 0.25 -1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd custom (at 0.25 -0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.302335) (xy 0.201556 -0.302335) (xy 0.201556 0.302335) (xy -0.110533 0.302335) (xy -0.201556 0.211312)) (width 0)) )) (pad "" smd rect (at 0.75 -1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd custom (at 0.75 -0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.302335) (xy 0.201556 -0.302335) (xy 0.201556 0.211312) (xy 0.110533 0.302335) (xy -0.201556 0.302335)) (width 0)) )) (pad "" smd custom (at -0.75 0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.211312) (xy -0.110533 -0.302335) (xy 0.201556 -0.302335) (xy 0.201556 0.302335) (xy -0.201556 0.302335)) (width 0)) )) (pad "" smd rect (at -0.75 1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd custom (at -0.25 0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.302335) (xy 0.110533 -0.302335) (xy 0.201556 -0.211312) (xy 0.201556 0.302335) (xy -0.201556 0.302335)) (width 0)) )) (pad "" smd rect (at -0.25 1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd custom (at 0.25 0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.211312) (xy -0.110533 -0.302335) (xy 0.201556 -0.302335) (xy 0.201556 0.302335) (xy -0.201556 0.302335)) (width 0)) )) (pad "" smd rect (at 0.25 1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd custom (at 0.75 0.375) (size 0.33875 0.33875) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.201556 -0.302335) (xy 0.110533 -0.302335) (xy 0.201556 -0.211312) (xy 0.201556 0.302335) (xy -0.201556 0.302335)) (width 0)) )) (pad "" smd rect (at 0.75 1.125) (size 0.403113 0.604669) (layers F.Paste)) (pad "" smd rect (at -1.5 -1.125) (size 0.806226 0.604669) (layers F.Paste)) (pad "" smd custom (at -1.5 -0.375) (size 0.574561 0.574561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.302335) (xy 0.403113 -0.302335) (xy 0.403113 0.259755) (xy 0.360533 0.302335) (xy -0.403113 0.302335)) (width 0)) )) (pad "" smd custom (at -1.5 0.375) (size 0.574561 0.574561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.302335) (xy 0.360533 -0.302335) (xy 0.403113 -0.259755) (xy 0.403113 0.302335) (xy -0.403113 0.302335)) (width 0)) )) (pad "" smd rect (at -1.5 1.125) (size 0.806226 0.604669) (layers F.Paste)) (pad "" smd rect (at 1.5 -1.125) (size 0.806226 0.604669) (layers F.Paste)) (pad "" smd custom (at 1.5 -0.375) (size 0.574561 0.574561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.302335) (xy 0.403113 -0.302335) (xy 0.403113 0.302335) (xy -0.360533 0.302335) (xy -0.403113 0.259755)) (width 0)) )) (pad "" smd custom (at 1.5 0.375) (size 0.574561 0.574561) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.259755) (xy -0.360533 -0.302335) (xy 0.403113 -0.302335) (xy 0.403113 0.302335) (xy -0.403113 0.302335)) (width 0)) )) (pad "" smd rect (at 1.5 1.125) (size 0.806226 0.604669) (layers F.Paste)) )""" RESULT_EP_PASTE_GEN_ONLY_OUTHER = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at 0 0) (size 2 2) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at 0 0) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 0) (size 0.6 0.6) (layers B.Cu)) (pad "" smd custom (at -0.5 -0.5) (size 0.743245 0.743245) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.403113) (xy 0.403113 -0.403113) (xy 0.403113 0.314044) (xy 0.314044 0.403113) (xy -0.403113 0.403113)) (width 0)) )) (pad "" smd custom (at -0.5 0.5) (size 0.743245 0.743245) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.403113) (xy 0.314044 -0.403113) (xy 0.403113 -0.314044) (xy 0.403113 0.403113) (xy -0.403113 0.403113)) (width 0)) )) (pad "" smd custom (at 0.5 -0.5) (size 0.743245 0.743245) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.403113) (xy 0.403113 -0.403113) (xy 0.403113 0.403113) (xy -0.314044 0.403113) (xy -0.403113 0.314044)) (width 0)) )) (pad "" smd custom (at 0.5 0.5) (size 0.743245 0.743245) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.403113 -0.314044) (xy -0.314044 -0.403113) (xy 0.403113 -0.403113) (xy 0.403113 0.403113) (xy -0.403113 0.403113)) (width 0)) )) )""" RESULT_EP_BOTTOM_PAD = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at -2 -2) (size 2 2) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at -2 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad "" smd rect (at -2 -2) (size 1.61 1.61) (layers F.Paste)) (pad 3 smd rect (at 2 -2) (size 2 2) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at 2 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 2 -2) (size 3 3) (layers B.Cu B.Mask)) (pad "" smd rect (at 2 -2) (size 1.61 1.61) (layers F.Paste)) )""" RESULT_EP_4x4 = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 33 smd rect (at 0 0) (size 3.55 3.55) (layers F.Cu F.Mask)) (pad 33 thru_hole circle (at -1 -1) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at 0 -1) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at 1 -1) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at -1 0) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at 0 0) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at 1 0) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at -1 1) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at 0 1) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 thru_hole circle (at 1 1) (size 0.5 0.5) (drill 0.2) (layers *.Cu)) (pad 33 smd rect (at 0 0) (size 2.5 2.5) (layers B.Cu)) (pad "" smd custom (at -0.5 -0.5) (size 0.733981 0.733981) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.329859) (xy -0.329859 -0.387298) (xy 0.329859 -0.387298) (xy 0.387298 -0.329859) (xy 0.387298 0.329859) (xy 0.329859 0.387298) (xy -0.329859 0.387298) (xy -0.387298 0.329859)) (width 0)) )) (pad "" smd custom (at -0.5 0.5) (size 0.733981 0.733981) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.329859) (xy -0.329859 -0.387298) (xy 0.329859 -0.387298) (xy 0.387298 -0.329859) (xy 0.387298 0.329859) (xy 0.329859 0.387298) (xy -0.329859 0.387298) (xy -0.387298 0.329859)) (width 0)) )) (pad "" smd custom (at 0.5 -0.5) (size 0.733981 0.733981) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.329859) (xy -0.329859 -0.387298) (xy 0.329859 -0.387298) (xy 0.387298 -0.329859) (xy 0.387298 0.329859) (xy 0.329859 0.387298) (xy -0.329859 0.387298) (xy -0.387298 0.329859)) (width 0)) )) (pad "" smd custom (at 0.5 0.5) (size 0.733981 0.733981) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.329859) (xy -0.329859 -0.387298) (xy 0.329859 -0.387298) (xy 0.387298 -0.329859) (xy 0.387298 0.329859) (xy 0.329859 0.387298) (xy -0.329859 0.387298) (xy -0.387298 0.329859)) (width 0)) )) (pad "" smd custom (at -1.3875 -0.5) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.387298) (xy 0.217359 -0.387298) (xy 0.300156 -0.304501) (xy 0.300156 0.304501) (xy 0.217359 0.387298) (xy -0.300156 0.387298)) (width 0)) )) (pad "" smd custom (at -1.3875 0.5) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.387298) (xy 0.217359 -0.387298) (xy 0.300156 -0.304501) (xy 0.300156 0.304501) (xy 0.217359 0.387298) (xy -0.300156 0.387298)) (width 0)) )) (pad "" smd custom (at 1.3875 -0.5) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.304501) (xy -0.217359 -0.387298) (xy 0.300156 -0.387298) (xy 0.300156 0.387298) (xy -0.217359 0.387298) (xy -0.300156 0.304501)) (width 0)) )) (pad "" smd custom (at 1.3875 0.5) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.304501) (xy -0.217359 -0.387298) (xy 0.300156 -0.387298) (xy 0.300156 0.387298) (xy -0.217359 0.387298) (xy -0.300156 0.304501)) (width 0)) )) (pad "" smd custom (at -0.5 -1.3875) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.300156) (xy 0.387298 -0.300156) (xy 0.387298 0.217359) (xy 0.304501 0.300156) (xy -0.304501 0.300156) (xy -0.387298 0.217359)) (width 0)) )) (pad "" smd custom (at 0.5 -1.3875) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.300156) (xy 0.387298 -0.300156) (xy 0.387298 0.217359) (xy 0.304501 0.300156) (xy -0.304501 0.300156) (xy -0.387298 0.217359)) (width 0)) )) (pad "" smd custom (at -0.5 1.3875) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.217359) (xy -0.304501 -0.300156) (xy 0.304501 -0.300156) (xy 0.387298 -0.217359) (xy 0.387298 0.300156) (xy -0.387298 0.300156)) (width 0)) )) (pad "" smd custom (at 0.5 1.3875) (size 0.541766 0.541766) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.387298 -0.217359) (xy -0.304501 -0.300156) (xy 0.304501 -0.300156) (xy 0.387298 -0.217359) (xy 0.387298 0.300156) (xy -0.387298 0.300156)) (width 0)) )) (pad "" smd custom (at -1.3875 -1.3875) (size 0.523835 0.523835) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.300156) (xy 0.300156 -0.300156) (xy 0.300156 0.192001) (xy 0.192001 0.300156) (xy -0.300156 0.300156)) (width 0)) )) (pad "" smd custom (at -1.3875 1.3875) (size 0.523835 0.523835) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.300156) (xy 0.192001 -0.300156) (xy 0.300156 -0.192001) (xy 0.300156 0.300156) (xy -0.300156 0.300156)) (width 0)) )) (pad "" smd custom (at 1.3875 -1.3875) (size 0.523835 0.523835) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.300156) (xy 0.300156 -0.300156) (xy 0.300156 0.300156) (xy -0.192001 0.300156) (xy -0.300156 0.192001)) (width 0)) )) (pad "" smd custom (at 1.3875 1.3875) (size 0.523835 0.523835) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.300156 -0.192001) (xy -0.192001 -0.300156) (xy 0.300156 -0.300156) (xy 0.300156 0.300156) (xy -0.300156 0.300156)) (width 0)) )) )""" RESULT_EP_AUTOGEN_EDGECASE_1 = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd rect (at -2 -2) (size 2 2) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at -2.7 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at -1.3 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at -2 -2) (size 2 0.6) (layers B.Cu)) (pad "" smd custom (at -2 -2.5) (size 0.770649 0.770649) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.564358 -0.403113) (xy 0.564358 -0.403113) (xy 0.564358 0.352799) (xy 0.514044 0.403113) (xy -0.514044 0.403113) (xy -0.564358 0.352799)) (width 0)) )) (pad "" smd custom (at -2 -1.5) (size 0.770649 0.770649) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.564358 -0.352799) (xy -0.514044 -0.403113) (xy 0.514044 -0.403113) (xy 0.564358 -0.352799) (xy 0.564358 0.403113) (xy -0.564358 0.403113)) (width 0)) )) (pad 3 smd rect (at 2 -2) (size 2 2) (layers F.Cu F.Mask)) (pad 3 thru_hole circle (at 1.3 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 2.7 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 2 -2) (size 2 0.6) (layers B.Cu)) (pad "" smd custom (at 2 -2.5) (size 0.770649 0.770649) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.564358 -0.403113) (xy 0.564358 -0.403113) (xy 0.564358 0.352799) (xy 0.514044 0.403113) (xy -0.514044 0.403113) (xy -0.564358 0.352799)) (width 0)) )) (pad "" smd custom (at 2 -1.5) (size 0.770649 0.770649) (layers F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.564358 -0.352799) (xy -0.514044 -0.403113) (xy 0.514044 -0.403113) (xy 0.564358 -0.352799) (xy 0.564358 0.403113) (xy -0.564358 0.403113)) (width 0)) )) (pad "" smd rect (at 0 3) (size 2 2) (layers F.Mask)) (pad 3 smd rect (at 0 3) (size 3 3) (layers F.Cu)) (pad 3 thru_hole circle (at -1.2 3) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 1.2 3) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 0 3) (size 3 0.6) (layers B.Cu)) (pad "" smd rect (at 0 2.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at 0 3.5) (size 1.61 0.81) (layers F.Paste)) )""" RESULT_EP_VIA_TENTING = """(module exposed_paste_autogen (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value exposed_paste_autogen (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad "" smd rect (at -2 -2) (size 2 2) (layers F.Mask)) (pad 3 smd rect (at -2 -2) (size 3 3) (layers F.Cu)) (pad 3 thru_hole circle (at -3.2 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu F.Mask B.Mask)) (pad 3 thru_hole circle (at -0.8 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu F.Mask B.Mask)) (pad 3 smd rect (at -2 -2) (size 3 0.6) (layers B.Cu)) (pad "" smd rect (at -2 -2.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at -2 -1.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at 2 -2) (size 2 2) (layers F.Mask)) (pad 3 smd rect (at 2 -2) (size 3 3) (layers F.Cu)) (pad 3 thru_hole circle (at 0.8 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu F.Mask)) (pad 3 thru_hole circle (at 3.2 -2) (size 0.6 0.6) (drill 0.3) (layers *.Cu F.Mask)) (pad 3 smd rect (at 2 -2) (size 3 0.6) (layers B.Cu)) (pad "" smd rect (at 2 -2.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at 2 -1.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at -2 2) (size 2 2) (layers F.Mask)) (pad 3 smd rect (at -2 2) (size 3 3) (layers F.Cu)) (pad 3 thru_hole circle (at -3.2 2) (size 0.6 0.6) (drill 0.3) (layers *.Cu B.Mask)) (pad 3 thru_hole circle (at -0.8 2) (size 0.6 0.6) (drill 0.3) (layers *.Cu B.Mask)) (pad 3 smd rect (at -2 2) (size 3 0.6) (layers B.Cu)) (pad "" smd rect (at -2 1.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at -2 2.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at 2 2) (size 2 2) (layers F.Mask)) (pad 3 smd rect (at 2 2) (size 3 3) (layers F.Cu)) (pad 3 thru_hole circle (at 0.8 2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 thru_hole circle (at 3.2 2) (size 0.6 0.6) (drill 0.3) (layers *.Cu)) (pad 3 smd rect (at 2 2) (size 3 0.6) (layers B.Cu)) (pad "" smd rect (at 2 1.5) (size 1.61 0.81) (layers F.Paste)) (pad "" smd rect (at 2 2.5) (size 1.61 0.81) (layers F.Paste)) )""" class ExposedPadTests(unittest.TestCase): def testSimpleExposedPad(self): kicad_mod = Footprint("simple_exposed") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="simple_exposed", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, at=[0, 1], size=[2.1, 3], mask_size=[2.1, 2.1], paste_layout=[2, 3], via_layout=[3, 2] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_SIMPLE_EP_FP) def testSimpleExposedPadNoRounding(self): kicad_mod = Footprint("simple_exposed") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="simple_exposed", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, at=[0, 1], size=[2.1, 3], mask_size=[2.1, 2.1], paste_layout=[2, 3], via_layout=[3, 2], grid_round_base=None, size_round_base=0 )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_SIMPLE_EP_NO_ROUNDING_FP) def testSimpleExposedMinimal(self): kicad_mod = Footprint("simple_exposed") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="simple_exposed", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[2.1, 3], paste_layout=2, via_layout=3 )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_MINIMAL_EP_SPECIFICATION) def testExposedPasteAutogenInner(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[5, 5], paste_layout=3, via_layout=2, paste_avoid_via=True )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_PASTE_GEN_INNER) def testExposedPasteAutogenInner2(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[5, 5], paste_layout=6, via_layout=4, paste_avoid_via=True, paste_coverage=0.5 )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep1.kicad_mod') self.assertEqual(result, RESULT_EP_PASTE_GEN_INNER2) def testExposedPasteAutogenInnerAndOuther(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[12, 8], paste_between_vias=2, paste_rings_outside=2, via_layout=3, paste_avoid_via=True, paste_coverage=0.7, via_grid=[3, 2], via_paste_clarance=0.25, min_annular_ring=0.25, at=[7, 5] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_PASTE_GEN_INNER_AND_OUTHER) def testExposedPasteAutogenInnerYonlyAndOuther(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[3, 5], paste_between_vias=2, paste_rings_outside=[2, 1], via_layout=[1, 3], paste_avoid_via=True, paste_coverage=0.65, via_grid=2, via_paste_clarance=0.15 )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_PASTE_GEN_INNER_ONLY_Y_AND_OUTHER) def testExposedPasteAutogenInnerXonlyAndOuther(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[4, 3], paste_between_vias=2, paste_rings_outside=[1, 2], via_layout=[3, 1], paste_avoid_via=True, paste_coverage=0.65, via_grid=1, via_paste_clarance=0.0 )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_PASTE_GEN_INNER_ONLY_X_AND_OUTHER) def testExposedPasteAutogenOnlyOuther(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[2, 2], paste_between_vias=0, paste_rings_outside=[1, 1], via_layout=[1, 1], paste_avoid_via=True, paste_coverage=0.65, via_grid=1.5 )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_PASTE_GEN_ONLY_OUTHER) def testExposedPasteBottomPadTests(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[2, 2], via_layout=[1, 1], at=[-2, -2], paste_coverage=0.65, via_grid=1, bottom_pad_Layers=None )) kicad_mod.append(ExposedPad( number=3, size=[2, 2], via_layout=[1, 1], at=[2, -2], paste_coverage=0.65, via_grid=1, bottom_pad_Layers=['B.Cu', 'B.Mask'], bottom_pad_min_size=[3, 3] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_BOTTOM_PAD) def testExposed4x4paste(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=33, size=[3.55, 3.55], paste_layout=[3, 3], paste_between_vias=1, paste_rings_outside=1, paste_coverage=0.6, via_layout=[3, 3], via_drill=0.2, via_grid=[1, 1], paste_avoid_via=True, via_paste_clarance=0.1, min_annular_ring=0.15, bottom_pad_min_size=[0, 0] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_4x4) def testExposedPadEdgeCase1(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[2, 2], via_layout=[2, 1], at=[-2, -2], paste_coverage=0.65, paste_layout=[1, 2], paste_avoid_via=True )) kicad_mod.append(ExposedPad( number=3, size=[2, 2], via_layout=[2, 1], at=[2, -2], paste_coverage=0.65, paste_layout=[1, 2], paste_avoid_via=True )) kicad_mod.append(ExposedPad( number=3, size=[3, 3], via_layout=[2, 1], at=[0, 3], paste_coverage=0.65, paste_layout=[1, 2], mask_size=[2, 2], paste_avoid_via=True )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_AUTOGEN_EDGECASE_1) def testExposedPasteViaTented(self): kicad_mod = Footprint("exposed_paste_autogen") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="exposed_paste_autogen", at=[0, 0], layer='F.Fab')) kicad_mod.append(ExposedPad( number=3, size=[3, 3], via_layout=[2, 1], at=[-2, -2], paste_coverage=0.65, paste_layout=[1, 2], mask_size=[2, 2], paste_avoid_via=True, via_tented=ExposedPad.VIA_NOT_TENTED )) kicad_mod.append(ExposedPad( number=3, size=[3, 3], via_layout=[2, 1], at=[2, -2], paste_coverage=0.65, paste_layout=[1, 2], mask_size=[2, 2], paste_avoid_via=True, via_tented=ExposedPad.VIA_TENTED_BOTTOM_ONLY )) kicad_mod.append(ExposedPad( number=3, size=[3, 3], via_layout=[2, 1], at=[-2, 2], paste_coverage=0.65, paste_layout=[1, 2], mask_size=[2, 2], paste_avoid_via=True, via_tented=ExposedPad.VIA_TENTED_TOP_ONLY )) kicad_mod.append(ExposedPad( number=3, size=[3, 3], via_layout=[2, 1], at=[2, 2], paste_coverage=0.65, paste_layout=[1, 2], mask_size=[2, 2], paste_avoid_via=True, via_tented=ExposedPad.VIA_TENTED )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_ep.kicad_mod') self.assertEqual(result, RESULT_EP_VIA_TENTING) ================================================ FILE: KicadModTree/tests/moduletests/test_kicad5_padshapes.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2018 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr from __future__ import division import unittest from KicadModTree import * RESULT_ROUNDRECT_FP = """(module round_rect_test (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value round_rect_test (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd roundrect (at 5 0 45) (size 1 1) (layers F.Cu F.Mask F.Paste) (roundrect_rratio 0.1)) (pad 2 smd roundrect (at -5 0) (size 1 1) (layers F.Cu F.Mask F.Paste) (roundrect_rratio 0.5)) (pad 1 smd rect (at 0 0) (size 1 1) (layers F.Cu F.Mask F.Paste)) )""" RESULT_ROUNDRECT_FP2 = """(module round_rect_test (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value round_rect_test (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 3 smd roundrect (at 5 0 45) (size 1 1) (layers F.Cu F.Mask F.Paste) (roundrect_rratio 0.25)) (pad 2 smd roundrect (at -5 0) (size 1 2) (layers F.Cu F.Mask F.Paste) (roundrect_rratio 0.25)) (pad 1 smd roundrect (at 0 0) (size 2 4) (layers F.Cu F.Mask F.Paste) (roundrect_rratio 0.125)) )""" RESULT_SIMPLE_POLYGON_PAD = """(module round_rect_test (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value round_rect_test (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 1 smd custom (at 0 0) (size 1 1) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1 -1) (xy 2 -1) (xy 1 1) (xy -1 2)) (width 0)) )) )""" RESULT_SIMPLE_OTHER_CUSTOM_PAD = """(module round_rect_test (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value round_rect_test (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 1 smd custom (at 0 0) (size 1 1) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_arc (start -1 0) (end -1 -0.5) (angle -180) (width 0.15)) (gr_line (start -1 -0.5) (end 1.25 -0.5) (width 0.15)) (gr_line (start 1.25 -0.5) (end 1.25 0.5) (width 0.15)) (gr_line (start 1.25 0.5) (end -1 0.5) (width 0.15)) )) (pad 2 smd custom (at 0 3) (size 1 1) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_arc (start -1 0) (end -1 -0.5) (angle -180) (width 0.15)) (gr_line (start -1 -0.5) (end 1.25 -0.5) (width 0.15)) (gr_line (start 1.25 -0.5) (end 1.25 0.5) (width 0.15)) (gr_line (start 1.25 0.5) (end -1 0.5) (width 0.15)) )) (pad 3 smd custom (at 0 -3) (size 1 1) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_circle (center 0.5 0.5) (end 1 0.5) (width 0.15)) )) )""" RESULT_CUT_POLYGON = """(module round_rect_test (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value round_rect_test (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 1 smd custom (at 0 0) (size 0.5 0.5) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -2 -2) (xy 2 -2) (xy 2 2) (xy 1 1) (xy 1 0) (xy 0 0) (xy 0 1) (xy 1 1) (xy 2 2) (xy -2 2)) (width 0)) )) )""" RESULT_CHAMFERED_PAD = """(module chamfered_pad (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value chamfered_pad (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 1 smd custom (at 0 0) (size 0.764298 0.764298) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.166667) (xy -0.166667 -0.5) (xy 0.166667 -0.5) (xy 0.5 -0.166667) (xy 0.5 0.166667) (xy 0.166667 0.5) (xy -0.166667 0.5) (xy -0.5 0.166667)) (width 0)) )) (pad 1 smd custom (at 2 2) (size 1.357538 1.357538) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1.05 -0.5) (xy -0.55 -1.55) (xy 0.55 -1.55) (xy 1.05 -0.5) (xy 1.05 0.5) (xy 0.55 1.55) (xy -0.55 1.55) (xy -1.05 0.5)) (width 0)) )) )""" RESULT_CHAMFERED_PAD_AVOID_CIRCLE = """(module test_avoid_circle (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value test_avoid_circle (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (fp_circle (center 3 3.5) (end 3.3 3.5) (layer F.SilkS) (width 0.01)) (pad 1 smd custom (at 2 2.5) (size 1.445 1.445) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.875 -0.693665) (xy -0.443665 -1.125) (xy 0.443665 -1.125) (xy 0.875 -0.693665) (xy 0.875 0.693665) (xy 0.443665 1.125) (xy -0.443665 1.125) (xy -0.875 0.693665)) (width 0)) )) )""" RESULT_CHAMFERED_PAD_GRID = """(module test_chamfered_grid (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value test_chamfered_grid (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 1 smd custom (at 0 -1.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.75) (xy -0.25 -1) (xy 0.5 -1) (xy 0.5 1) (xy -0.25 1) (xy -0.5 0.75)) (width 0)) )) (pad 1 smd custom (at 0 1.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.75) (xy -0.25 -1) (xy 0.5 -1) (xy 0.5 1) (xy -0.25 1) (xy -0.5 0.75)) (width 0)) )) (pad 1 smd custom (at 0 3.75) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.75) (xy -0.25 -1) (xy 0.5 -1) (xy 0.5 1) (xy -0.25 1) (xy -0.5 0.75)) (width 0)) )) (pad 1 smd custom (at 0 6.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.75) (xy -0.25 -1) (xy 0.5 -1) (xy 0.5 1) (xy -0.25 1) (xy -0.5 0.75)) (width 0)) )) (pad 1 smd custom (at 1.5 -1.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.75) (xy -0.25 -1) (xy 0.25 -1) (xy 0.5 -0.75) (xy 0.5 1) (xy -0.5 1)) (width 0)) )) (pad 1 smd rect (at 1.5 1.25) (size 1 2) (layers F.Cu F.Mask F.Paste)) (pad 1 smd rect (at 1.5 3.75) (size 1 2) (layers F.Cu F.Mask F.Paste)) (pad 1 smd custom (at 1.5 6.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -1) (xy 0.5 -1) (xy 0.5 0.75) (xy 0.25 1) (xy -0.25 1) (xy -0.5 0.75)) (width 0)) )) (pad 1 smd custom (at 3 -1.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -1) (xy 0.25 -1) (xy 0.5 -0.75) (xy 0.5 0.75) (xy 0.25 1) (xy -0.5 1)) (width 0)) )) (pad 1 smd custom (at 3 1.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -1) (xy 0.25 -1) (xy 0.5 -0.75) (xy 0.5 0.75) (xy 0.25 1) (xy -0.5 1)) (width 0)) )) (pad 1 smd custom (at 3 3.75) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -1) (xy 0.25 -1) (xy 0.5 -0.75) (xy 0.5 0.75) (xy 0.25 1) (xy -0.5 1)) (width 0)) )) (pad 1 smd custom (at 3 6.25) (size 0.823223 0.823223) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -1) (xy 0.25 -1) (xy 0.5 -0.75) (xy 0.5 0.75) (xy 0.25 1) (xy -0.5 1)) (width 0)) )) )""" RESULT_CHAMFERED_PAD_GRID_AVOID_CIRCLE = """(module test_chamfered_grid (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value test_chamfered_grid (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (fp_circle (center 2 2.5) (end 2.2 2.5) (layer F.SilkS) (width 0.01)) (pad 1 smd custom (at -1.4 -2.1) (size 0.795 0.795) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.210086) (xy -0.210086 -0.5) (xy 0.5 -0.5) (xy 0.5 0.5) (xy -0.5 0.5)) (width 0)) )) (pad 1 smd rect (at -1.4 -0.7) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd rect (at -1.4 0.7) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd custom (at -1.4 2.1) (size 0.795 0.795) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.5) (xy 0.5 -0.5) (xy 0.5 0.5) (xy -0.210086 0.5) (xy -0.5 0.210086)) (width 0)) )) (pad 1 smd rect (at 0 -2.1) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd rect (at 0 -0.7) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd rect (at 0 0.7) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd rect (at 0 2.1) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd custom (at 1.4 -2.1) (size 0.795 0.795) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.5) (xy 0.210086 -0.5) (xy 0.5 -0.210086) (xy 0.5 0.5) (xy -0.5 0.5)) (width 0)) )) (pad 1 smd rect (at 1.4 -0.7) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd rect (at 1.4 0.7) (size 1 1) (layers F.Cu F.Mask F.Paste)) (pad 1 smd custom (at 1.4 2.1) (size 0.795 0.795) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -0.5 -0.5) (xy 0.5 -0.5) (xy 0.5 0.210086) (xy 0.210086 0.5) (xy -0.5 0.5)) (width 0)) )) )""" RESULT_CHAMFERED_ROUNDED_PAD = """(module chamfered_pad (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value chamfered_pad (at 0 0) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (pad 1 smd custom (at 0 0) (size 3.646447 3.646447) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -2 -1.5) (xy -1.5 -2) (xy 1.5 -2) (xy 2 -1.5) (xy 2 1.5) (xy 1.5 2) (xy -1.5 2) (xy -2 1.5)) (width 0)) )) (pad 1 smd roundrect (at 0 0) (size 4 4) (layers B.Cu) (roundrect_rratio 0.25)) (pad 1 smd custom (at 0 5) (size 2.292893 2.292893) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -2 -0.5) (xy -1 -1.5) (xy 1 -1.5) (xy 2 -0.5) (xy 2 0.5) (xy 1 1.5) (xy -1 1.5) (xy -2 0.5)) (width 0)) )) (pad 1 smd custom (at 0 5) (size 2.292893 2.292893) (layers B.Cu) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1.292893 -0.207107) (xy -0.707107 -0.792893) (xy 0.707107 -0.792893) (xy 1.292893 -0.207107) (xy 1.292893 0.207107) (xy 0.707107 0.792893) (xy -0.707107 0.792893) (xy -1.292893 0.207107)) (width 1.414214)) )) (pad 1 smd custom (at 5 0) (size 2.292893 2.292893) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -2 -0.5) (xy -1 -1.5) (xy 2 -1.5) (xy 2 0.5) (xy 1 1.5) (xy -2 1.5)) (width 0)) )) (pad 1 smd custom (at 5 0) (size 2.292893 2.292893) (layers B.Cu) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1.292893 -0.207107) (xy -0.707107 -0.792893) (xy 1.292893 -0.792893) (xy 1.292893 0.207107) (xy 0.707107 0.792893) (xy -1.292893 0.792893)) (width 1.414214)) )) )""" # NOQA: E501 class Kicad5PadsTests(unittest.TestCase): def testRoundRectPad(self): kicad_mod = Footprint("round_rect_test") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="round_rect_test", at=[0, 0], layer='F.Fab')) kicad_mod.append(Pad(number=3, type=Pad.TYPE_SMT, shape=Pad.SHAPE_ROUNDRECT, at=[5, 0], rotation=45, size=[1, 1], layers=Pad.LAYERS_SMT, radius_ratio=0.1)) kicad_mod.append(Pad(number=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_ROUNDRECT, at=[-5, 0], size=[1, 1], layers=Pad.LAYERS_SMT, radius_ratio=0.5)) kicad_mod.append(Pad(number=1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_ROUNDRECT, at=[0, 0], size=[1, 1], layers=Pad.LAYERS_SMT, radius_ratio=0)) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test.kicad_mod') self.assertEqual(result, RESULT_ROUNDRECT_FP) def testRoundRectPad2(self): kicad_mod = Footprint("round_rect_test") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="round_rect_test", at=[0, 0], layer='F.Fab')) kicad_mod.append(Pad(number=3, type=Pad.TYPE_SMT, shape=Pad.SHAPE_ROUNDRECT, at=[5, 0], rotation=45, size=[1, 1], layers=Pad.LAYERS_SMT, radius_ratio=0.25, maximum_radius=0.25)) kicad_mod.append(Pad(number=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_ROUNDRECT, at=[-5, 0], size=[1, 2], layers=Pad.LAYERS_SMT, radius_ratio=0.25, maximum_radius=0.25)) kicad_mod.append(Pad(number=1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_ROUNDRECT, at=[0, 0], size=[2, 4], layers=Pad.LAYERS_SMT, radius_ratio=0.25, maximum_radius=0.25)) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_max_radius.kicad_mod') self.assertEqual(result, RESULT_ROUNDRECT_FP2) def testPolygonPad(self): kicad_mod = Footprint("round_rect_test") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="round_rect_test", at=[0, 0], layer='F.Fab')) kicad_mod.append(Pad(number=1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=[0, 0], size=[1, 1], layers=Pad.LAYERS_SMT, primitives=[Polygon(nodes=[(-1, -1), (2, -1), (1, 1), (-1, 2)])] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test.kicad_mod') self.assertEqual(result, RESULT_SIMPLE_POLYGON_PAD) def testCustomPadOtherPrimitives(self): kicad_mod = Footprint("round_rect_test") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="round_rect_test", at=[0, 0], layer='F.Fab')) kicad_mod.append( Pad(number=1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=[0, 0], size=[1, 1], layers=Pad.LAYERS_SMT, primitives=[ Arc(center=(-1, 0), start=(-1, -0.5), angle=-180, width=0.15), Line(start=(-1, -0.5), end=(1.25, -0.5), width=0.15), Line(start=(1.25, -0.5), end=(1.25, 0.5), width=0.15), Line(start=(1.25, 0.5), end=(-1, 0.5), width=0.15) ] )) kicad_mod.append( Pad(number=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=[0, 3], size=[1, 1], layers=Pad.LAYERS_SMT, primitives=[ Arc(center=(-1, 0), start=(-1, -0.5), angle=-180, width=0.15), PolygoneLine(nodes=[(-1, -0.5), (1.25, -0.5), (1.25, 0.5), (-1, 0.5)], width=0.15) ] )) kicad_mod.append( Pad(number=3, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=[0, -3], size=[1, 1], layers=Pad.LAYERS_SMT, primitives=[ Circle(center=(0.5, 0.5), radius=0.5, width=0.15) ] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test.kicad_mod') self.assertEqual(result, RESULT_SIMPLE_OTHER_CUSTOM_PAD) def testCutPolygon(self): kicad_mod = Footprint("round_rect_test") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="round_rect_test", at=[0, 0], layer='F.Fab')) p1 = Polygon(nodes=[(0, 0), (1, 0), (1, 1), (0, 1)]) p2 = Polygon(nodes=[(-2, -2), (2, -2), (2, 2), (-2, 2)]) p2.cut(p1) kicad_mod.append(Pad(number=1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=[0, 0], size=[0.5, 0.5], layers=Pad.LAYERS_SMT, primitives=[p2] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test.kicad_mod') self.assertEqual(result, RESULT_CUT_POLYGON) def testChamferedPad(self): kicad_mod = Footprint("chamfered_pad") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="chamfered_pad", at=[0, 0], layer='F.Fab')) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[0, 0], size=[1, 1], layers=Pad.LAYERS_SMT, chamfer_size=[1/3, 1/3], corner_selection=[1, 1, 1, 1] )) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[2, 2], size=[2.1, 3.1], layers=Pad.LAYERS_SMT, chamfer_size=[0.5, 1.05], corner_selection=[1, 1, 1, 1] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_cp.kicad_mod') self.assertEqual(result, RESULT_CHAMFERED_PAD) def testChamferedPadAvoidCircle(self): kicad_mod = Footprint("test_avoid_circle") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="test_avoid_circle", at=[0, 0], layer='F.Fab')) pad = ChamferedPad( number=1, type=Pad.TYPE_SMT, at=[2, 2.5], size=[1.75, 2.25], layers=Pad.LAYERS_SMT, chamfer_size=[0.25, 0.25], corner_selection=[1, 1, 1, 1] ) c = [3, 3.5] d = 0.6 kicad_mod.append(Circle(center=c, radius=d/2, width=0.01)) pad.chamferAvoidCircle(center=c, diameter=d, clearance=0.005) kicad_mod.append(pad) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_avoid_circle.kicad_mod') self.assertEqual(result, RESULT_CHAMFERED_PAD_AVOID_CIRCLE) def testChamferedPadGrid(self): kicad_mod = Footprint("test_chamfered_grid") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="test_chamfered_grid", at=[0, 0], layer='F.Fab')) kicad_mod.append( ChamferedPadGrid( number=1, type=Pad.TYPE_SMT, center=[1.5, 2.5], size=[1, 2], layers=Pad.LAYERS_SMT, chamfer_size=[0.25, 0.25], chamfer_selection=1, pincount=[3, 4], grid=[1.5, 2.5] )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_chamfered_grid.kicad_mod') self.assertEqual(result, RESULT_CHAMFERED_PAD_GRID) def testChamferedPadGridCornerOnly(self): kicad_mod = Footprint("test_chamfered_grid") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="test_chamfered_grid", at=[0, 0], layer='F.Fab')) chamfer_select = ChamferSelPadGrid(0) chamfer_select.setCorners() pad = ChamferedPadGrid( number=1, type=Pad.TYPE_SMT, center=[0, 0], size=[1, 1], layers=Pad.LAYERS_SMT, chamfer_size=[0.25, 0.25], chamfer_selection=chamfer_select, pincount=[3, 4], grid=[1.4, 1.4] ) c = [2.0, 2.5] d = 0.4 kicad_mod.append(Circle(center=c, radius=d/2, width=0.01)) pad.chamferAvoidCircle(center=c, diameter=d, clearance=0.005) kicad_mod.append(pad) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_chamfered_grid.kicad_mod') self.assertEqual(result, RESULT_CHAMFERED_PAD_GRID_AVOID_CIRCLE) def testChamferedRoundedPad(self): kicad_mod = Footprint("chamfered_pad") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, 0], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="chamfered_pad", at=[0, 0], layer='F.Fab')) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[0, 0], size=[4, 4], layers=Pad.LAYERS_SMT, chamfer_size=[0.5, 0.5], corner_selection=[1, 1, 1, 1] )) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[0, 0], size=[4, 4], layers=["B.Cu"], chamfer_size=[0.5, 0.5], corner_selection=[1, 1, 1, 1], radius_ratio=0.25 )) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[0, 5], size=[4, 3], layers=Pad.LAYERS_SMT, chamfer_size=[1, 1], corner_selection=[1, 1, 1, 1] )) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[0, 5], size=[4, 3], layers=["B.Cu"], chamfer_size=[1, 1], corner_selection=[1, 1, 1, 1], radius_ratio=0.25 )) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[5, 0], size=[4, 3], layers=Pad.LAYERS_SMT, chamfer_size=[1, 1], corner_selection=[1, 0, 1, 0] )) kicad_mod.append( ChamferedPad(number=1, type=Pad.TYPE_SMT, at=[5, 0], size=[4, 3], layers=["B.Cu"], chamfer_size=[1, 1], corner_selection=[1, 0, 1, 0], radius_ratio=0.25 )) file_handler = KicadFileHandler(kicad_mod) result = file_handler.serialize(timestamp=0) # file_handler.writeFile('test_cp.kicad_mod') self.assertEqual(result, RESULT_CHAMFERED_ROUNDED_PAD) ================================================ FILE: KicadModTree/tests/moduletests/test_rotation.py ================================================ import unittest import math from KicadModTree import * RESULT_rotText = """(module test_rotate (layer F.Cu) (tedit 0) (fp_text user -1 (at 2 0) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text user -1 (at 1.414214 1.414214 -45) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text user -1 (at 0 2 -90) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text user -1 (at -1.414214 1.414214 -135) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text user -1 (at -2 0 -180) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text user -1 (at -1.414214 -1.414214 -225) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text user -1 (at 0 -2 -270) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text user -1 (at 1.414214 -1.414214 -315) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) )""" RESULT_rotLine = """(module test_rotate (layer F.Cu) (tedit 0) (fp_line (start 6 0) (end 7 1) (layer F.SilkS) (width 0.12)) (fp_line (start 5.931852 0.517638) (end 6.638958 1.742383) (layer F.SilkS) (width 0.12)) (fp_line (start 5.732051 1) (end 6.098076 2.366025) (layer F.SilkS) (width 0.12)) (fp_line (start 5.414214 1.414214) (end 5.414214 2.828427) (layer F.SilkS) (width 0.12)) (fp_line (start 5 1.732051) (end 4.633975 3.098076) (layer F.SilkS) (width 0.12)) (fp_line (start 4.517638 1.931852) (end 3.810531 3.156597) (layer F.SilkS) (width 0.12)) (fp_line (start 4 2) (end 3 3) (layer F.SilkS) (width 0.12)) (fp_line (start 3.482362 1.931852) (end 2.257617 2.638958) (layer F.SilkS) (width 0.12)) (fp_line (start 3 1.732051) (end 1.633975 2.098076) (layer F.SilkS) (width 0.12)) (fp_line (start 2.585786 1.414214) (end 1.171573 1.414214) (layer F.SilkS) (width 0.12)) (fp_line (start 2.267949 1) (end 0.901924 0.633975) (layer F.SilkS) (width 0.12)) (fp_line (start 2.068148 0.517638) (end 0.843403 -0.189469) (layer F.SilkS) (width 0.12)) (fp_line (start 2 0) (end 1 -1) (layer F.SilkS) (width 0.12)) (fp_line (start 2.068148 -0.517638) (end 1.361042 -1.742383) (layer F.SilkS) (width 0.12)) (fp_line (start 2.267949 -1) (end 1.901924 -2.366025) (layer F.SilkS) (width 0.12)) (fp_line (start 2.585786 -1.414214) (end 2.585786 -2.828427) (layer F.SilkS) (width 0.12)) (fp_line (start 3 -1.732051) (end 3.366025 -3.098076) (layer F.SilkS) (width 0.12)) (fp_line (start 3.482362 -1.931852) (end 4.189469 -3.156597) (layer F.SilkS) (width 0.12)) (fp_line (start 4 -2) (end 5 -3) (layer F.SilkS) (width 0.12)) (fp_line (start 4.517638 -1.931852) (end 5.742383 -2.638958) (layer F.SilkS) (width 0.12)) (fp_line (start 5 -1.732051) (end 6.366025 -2.098076) (layer F.SilkS) (width 0.12)) (fp_line (start 5.414214 -1.414214) (end 6.828427 -1.414214) (layer F.SilkS) (width 0.12)) (fp_line (start 5.732051 -1) (end 7.098076 -0.633975) (layer F.SilkS) (width 0.12)) (fp_line (start 5.931852 -0.517638) (end 7.156597 0.189469) (layer F.SilkS) (width 0.12)) )""" RESULT_rotArc = """(module test_rotate (layer F.Cu) (tedit 0) (fp_arc (start 6 1) (end 5.741181 0.034074) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 5.673033 1.483564) (end 5.673033 0.483564) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 5.232051 1.866025) (end 5.49087 0.9001) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 4.707107 2.12132) (end 5.207107 1.255295) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 4.133975 2.232051) (end 4.841081 1.524944) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 3.551712 2.190671) (end 4.417738 1.690671) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 3 2) (end 3.965926 1.741181) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 2.516436 1.673033) (end 3.516436 1.673033) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 2.133975 1.232051) (end 3.0999 1.49087) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 1.87868 0.707107) (end 2.744705 1.207107) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 1.767949 0.133975) (end 2.475056 0.841081) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 1.809329 -0.448288) (end 2.309329 0.417738) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 2 -1) (end 2.258819 -0.034074) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 2.326967 -1.483564) (end 2.326967 -0.483564) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 2.767949 -1.866025) (end 2.50913 -0.9001) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 3.292893 -2.12132) (end 2.792893 -1.255295) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 3.866025 -2.232051) (end 3.158919 -1.524944) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 4.448288 -2.190671) (end 3.582262 -1.690671) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 5 -2) (end 4.034074 -1.741181) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 5.483564 -1.673033) (end 4.483564 -1.673033) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 5.866025 -1.232051) (end 4.9001 -1.49087) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 6.12132 -0.707107) (end 5.255295 -1.207107) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 6.232051 -0.133975) (end 5.524944 -0.841081) (angle 90) (layer F.SilkS) (width 0.12)) (fp_arc (start 6.190671 0.448288) (end 5.690671 -0.417738) (angle 90) (layer F.SilkS) (width 0.12)) )""" RESULT_rotCircle = """(module test_rotate (layer F.Cu) (tedit 0) (fp_circle (center 6 -1) (end 7 -1) (layer F.SilkS) (width 0.12)) (fp_circle (center 5.673033 -0.516436) (end 6.673033 -0.516436) (layer F.SilkS) (width 0.12)) (fp_circle (center 5.232051 -0.133975) (end 6.232051 -0.133975) (layer F.SilkS) (width 0.12)) (fp_circle (center 4.707107 0.12132) (end 5.707107 0.12132) (layer F.SilkS) (width 0.12)) (fp_circle (center 4.133975 0.232051) (end 5.133975 0.232051) (layer F.SilkS) (width 0.12)) (fp_circle (center 3.551712 0.190671) (end 4.551712 0.190671) (layer F.SilkS) (width 0.12)) (fp_circle (center 3 0) (end 4 0) (layer F.SilkS) (width 0.12)) (fp_circle (center 2.516436 -0.326967) (end 3.516436 -0.326967) (layer F.SilkS) (width 0.12)) (fp_circle (center 2.133975 -0.767949) (end 3.133975 -0.767949) (layer F.SilkS) (width 0.12)) (fp_circle (center 1.87868 -1.292893) (end 2.87868 -1.292893) (layer F.SilkS) (width 0.12)) (fp_circle (center 1.767949 -1.866025) (end 2.767949 -1.866025) (layer F.SilkS) (width 0.12)) (fp_circle (center 1.809329 -2.448288) (end 2.809329 -2.448288) (layer F.SilkS) (width 0.12)) (fp_circle (center 2 -3) (end 3 -3) (layer F.SilkS) (width 0.12)) (fp_circle (center 2.326967 -3.483564) (end 3.326967 -3.483564) (layer F.SilkS) (width 0.12)) (fp_circle (center 2.767949 -3.866025) (end 3.767949 -3.866025) (layer F.SilkS) (width 0.12)) (fp_circle (center 3.292893 -4.12132) (end 4.292893 -4.12132) (layer F.SilkS) (width 0.12)) (fp_circle (center 3.866025 -4.232051) (end 4.866025 -4.232051) (layer F.SilkS) (width 0.12)) (fp_circle (center 4.448288 -4.190671) (end 5.448288 -4.190671) (layer F.SilkS) (width 0.12)) (fp_circle (center 5 -4) (end 6 -4) (layer F.SilkS) (width 0.12)) (fp_circle (center 5.483564 -3.673033) (end 6.483564 -3.673033) (layer F.SilkS) (width 0.12)) (fp_circle (center 5.866025 -3.232051) (end 6.866025 -3.232051) (layer F.SilkS) (width 0.12)) (fp_circle (center 6.12132 -2.707107) (end 7.12132 -2.707107) (layer F.SilkS) (width 0.12)) (fp_circle (center 6.232051 -2.133975) (end 7.232051 -2.133975) (layer F.SilkS) (width 0.12)) (fp_circle (center 6.190671 -1.551712) (end 7.190671 -1.551712) (layer F.SilkS) (width 0.12)) )""" RESULT_rotPoly = """(module test_rotate (layer F.Cu) (tedit 0) (fp_poly (pts (xy -1 0) (xy -1.2 0.5) (xy 0 0) (xy -1.2 -0.5)) (layer F.SilkS) (width 0.12)) (fp_poly (pts (xy -0.575833 -3.334679) (xy -1.108846 -3.257884) (xy -0.075833 -2.468653) (xy -0.24282 -3.757884)) (layer F.SilkS) (width 0.12)) (fp_poly (pts (xy 2.524167 -4.634679) (xy 2.191154 -5.057884) (xy 2.024167 -3.768653) (xy 3.05718 -4.557884)) (layer F.SilkS) (width 0.12)) (fp_poly (pts (xy 5.2 -2.6) (xy 5.4 -3.1) (xy 4.2 -2.6) (xy 5.4 -2.1)) (layer F.SilkS) (width 0.12)) (fp_poly (pts (xy 4.775833 0.734679) (xy 5.308846 0.657884) (xy 4.275833 -0.131347) (xy 4.44282 1.157884)) (layer F.SilkS) (width 0.12)) (fp_poly (pts (xy 1.675833 2.034679) (xy 2.008846 2.457884) (xy 2.175833 1.168653) (xy 1.14282 1.957884)) (layer F.SilkS) (width 0.12)) )""" # NOQA: E501 RESULT_rotPad = """(module test_rotate (layer F.Cu) (tedit 0) (pad 1 smd custom (at 0 0) (size 0.2 0.2) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1 0) (xy -1.2 0.5) (xy 0 0) (xy -1.2 -0.5)) (width 0)) )) (pad 2 smd custom (at 0.175 -0.303109 -60) (size 0.2 0.2) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1 0) (xy -1.2 0.5) (xy 0 0) (xy -1.2 -0.5)) (width 0)) )) (pad 3 smd custom (at 0.525 -0.303109 -120) (size 0.2 0.2) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1 0) (xy -1.2 0.5) (xy 0 0) (xy -1.2 -0.5)) (width 0)) )) (pad 4 smd custom (at 0.7 0 -180) (size 0.2 0.2) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1 0) (xy -1.2 0.5) (xy 0 0) (xy -1.2 -0.5)) (width 0)) )) (pad 5 smd custom (at 0.525 0.303109 -240) (size 0.2 0.2) (layers F.Cu F.Mask F.Paste) (options (clearance outline) (anchor circle)) (primitives (gr_poly (pts (xy -1 0) (xy -1.2 0.5) (xy 0 0) (xy -1.2 -0.5)) (width 0)) )) )""" class RotationTests(unittest.TestCase): def testTextRotation(self): kicad_mod = Footprint("test_rotate") center = Vector2D(0, 0) at = center+Vector2D(2, 0) for t in range(0, 360, 45): kicad_mod.append( Text(type=Text.TYPE_USER, text="-1", at=at).rotate(t, origin=center)) file_handler = KicadFileHandler(kicad_mod) # file_handler.writeFile('test.kicad_mod') self.assertEqual(file_handler.serialize(timestamp=0), RESULT_rotText) def testLineRotation(self): kicad_mod = Footprint("test_rotate") center = Vector2D(4, 0) start = center + Vector2D(2, 0) end = start + Vector2D(1, 1) for t in range(0, 360, 15): kicad_mod.append( Line(start=start, end=end).rotate(t, origin=center)) file_handler = KicadFileHandler(kicad_mod) # file_handler.writeFile('test.kicad_mod') self.assertEqual(file_handler.serialize(timestamp=0), RESULT_rotLine) def testArcRotation(self): kicad_mod = Footprint("test_rotate") rot_center = Vector2D(4, 0) mid = rot_center + Vector2D(2, 0) center = rot_center + Vector2D(2, 1) angle = 90 for t in range(0, 360, 15): kicad_mod.append( Arc(center=center, midpoint=mid, angle=angle) .rotate(angle/3, origin=center) .rotate(t, origin=rot_center)) file_handler = KicadFileHandler(kicad_mod) # file_handler.writeFile('test.kicad_mod') self.assertEqual(file_handler.serialize(timestamp=0), RESULT_rotArc) def testCircleRotation(self): kicad_mod = Footprint("test_rotate") rot_center = Vector2D(4, -2) center = rot_center + Vector2D(2, 1) radius = 1 for t in range(0, 360, 15): kicad_mod.append( Circle(center=center, radius=radius).rotate(t, origin=rot_center)) file_handler = KicadFileHandler(kicad_mod) # file_handler.writeFile('test.kicad_mod') self.assertEqual(file_handler.serialize(timestamp=0), RESULT_rotCircle) def testPolygonRotation(self): kicad_mod = Footprint("test_rotate") rot_center = Vector2D(2.1, -1.3) nodes = [(-1, 0), (-1.2, 0.5), (0, 0), (-1.2, -0.5)] for t in range(0, 360, 60): kicad_mod.append( Polygon(nodes=nodes).rotate(t, origin=rot_center)) file_handler = KicadFileHandler(kicad_mod) # file_handler.writeFile('test.kicad_mod') self.assertEqual(file_handler.serialize(timestamp=0), RESULT_rotPoly) def testPadRotation(self): kicad_mod = Footprint("test_rotate") rot_center = Vector2D(0.35, 0) nodes = [(-1, 0), (-1.2, 0.5), (0, 0), (-1.2, -0.5)] prim = Polygon(nodes=nodes) i = 1 for t in range(0, 300, 60): kicad_mod.append( Pad( number=i, type=Pad.TYPE_SMT, shape=Pad.SHAPE_CUSTOM, at=[0, 0], size=[0.2, 0.2], layers=Pad.LAYERS_SMT, primitives=[prim] ).rotate(t, origin=rot_center)) i += 1 file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('test.kicad_mod') self.assertEqual(file_handler.serialize(timestamp=0), RESULT_rotPad) ================================================ FILE: KicadModTree/tests/moduletests/test_simple_footprints.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2018 by Thomas Pointhuber, import unittest from KicadModTree import * RESULT_MINIMUM = """(module test (layer F.Cu) (tedit 0) )""" RESULT_BASIC_TAGS = """(module test (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (attr smd) )""" RESULT_SIMPLE_FOOTPRINT = """(module test (layer F.Cu) (tedit 0) (descr "A example footprint") (tags example) (fp_text reference REF** (at 0 -3) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value test (at 1.5 3) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (fp_line (start -2 -2) (end -2 2) (layer F.SilkS) (width 0.12)) (fp_line (start -2 2) (end 5 2) (layer F.SilkS) (width 0.12)) (fp_line (start 5 2) (end 5 -2) (layer F.SilkS) (width 0.12)) (fp_line (start 5 -2) (end -2 -2) (layer F.SilkS) (width 0.12)) (fp_line (start -2.25 -2.25) (end -2.25 2.25) (layer F.CrtYd) (width 0.05)) (fp_line (start -2.25 2.25) (end 5.25 2.25) (layer F.CrtYd) (width 0.05)) (fp_line (start 5.25 2.25) (end 5.25 -2.25) (layer F.CrtYd) (width 0.05)) (fp_line (start 5.25 -2.25) (end -2.25 -2.25) (layer F.CrtYd) (width 0.05)) (pad 1 thru_hole rect (at 0 0) (size 2 2) (drill 1.2) (layers *.Cu *.Mask)) (pad 2 thru_hole circle (at 3 0) (size 2 2) (drill 1.2) (layers *.Cu *.Mask)) (model example.3dshapes/example_footprint.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) )""" RESULT_BASIC_NODES = """(module test (layer F.Cu) (tedit 0) (fp_text reference REF** (at 0 -3) (layer F.SilkS) (effects (font (size 1 1) (thickness 0.15))) ) (fp_text value "footprint name" (at 0 3) (layer F.Fab) (effects (font (size 1 1) (thickness 0.15))) ) (fp_arc (start 0 0) (end -1 0) (angle 180) (layer F.SilkS) (width 0.12)) (fp_circle (center 0 0) (end 1.5 0) (layer F.SilkS) (width 0.12)) (fp_line (start 1 0) (end -1 0) (layer F.SilkS) (width 0.12)) (pad 1 thru_hole rect (at 0 0) (size 2 2) (drill 1.2) (layers *.Cu *.Mask)) (model example.3dshapes/example_footprint.wrl (at (xyz 0 0 0)) (scale (xyz 1 1 1)) (rotate (xyz 0 0 0)) ) )""" class SimpleFootprintTests(unittest.TestCase): def testMinimum(self): kicad_mod = Footprint("test") file_handler = KicadFileHandler(kicad_mod) self.assertEqual(file_handler.serialize(timestamp=0), RESULT_MINIMUM) def testBasicTags(self): kicad_mod = Footprint("test") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.setAttribute("smd") file_handler = KicadFileHandler(kicad_mod) self.assertEqual(file_handler.serialize(timestamp=0), RESULT_BASIC_TAGS) def testSampleFootprint(self): kicad_mod = Footprint("test") kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") kicad_mod.append(Text(type='reference', text='REF**', at=[0, -3], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="test", at=[1.5, 3], layer='F.Fab')) kicad_mod.append(RectLine(start=[-2, -2], end=[5, 2], layer='F.SilkS')) kicad_mod.append(RectLine(start=[-2.25, -2.25], end=[5.25, 2.25], layer='F.CrtYd')) kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[3, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT)) kicad_mod.append(Model(filename="example.3dshapes/example_footprint.wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) file_handler = KicadFileHandler(kicad_mod) self.assertEqual(file_handler.serialize(timestamp=0), RESULT_SIMPLE_FOOTPRINT) def testBasicNodes(self): kicad_mod = Footprint("test") kicad_mod.append(Text(type='reference', text='REF**', at=[0, -3], layer='F.SilkS')) kicad_mod.append(Text(type='value', text="footprint name", at=[0, 3], layer='F.Fab')) kicad_mod.append(Arc(center=[0, 0], start=[-1, 0], angle=180, layer='F.SilkS')) kicad_mod.append(Circle(center=[0, 0], radius=1.5, layer='F.SilkS')) kicad_mod.append(Line(start=[1, 0], end=[-1, 0], layer='F.SilkS')) kicad_mod.append(Model(filename="example.3dshapes/example_footprint.wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT)) file_handler = KicadFileHandler(kicad_mod) self.assertEqual(file_handler.serialize(timestamp=0), RESULT_BASIC_NODES) ================================================ FILE: KicadModTree/tests/nodes/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, from .test_Node import NodeTests ================================================ FILE: KicadModTree/tests/nodes/test_Node.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import unittest from KicadModTree.nodes.Node import * class TestChildNode(Node): def __init__(self): Node.__init__(self) class NodeTests(unittest.TestCase): def testInit(self): node = Node() self.assertIs(node.getParent(), None) self.assertIs(node.getRootNode(), node) self.assertEqual(len(node.getNormalChilds()), 0) self.assertEqual(len(node.getVirtualChilds()), 0) self.assertEqual(len(node.getAllChilds()), 0) def testAppend(self): node = Node() self.assertEqual(len(node.getNormalChilds()), 0) childNode1 = Node() node.append(childNode1) self.assertIn(childNode1, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) childNode2 = Node() node.append(childNode2) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 2) with self.assertRaises(TypeError): node.append(None) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 2) with self.assertRaises(TypeError): node.append(object) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 2) with self.assertRaises(TypeError): node.append("a string is not a node object") self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 2) with self.assertRaises(MultipleParentsError): node.append(childNode1) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 2) childNode3 = TestChildNode() node.append(childNode3) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 3) def testExtend(self): node = Node() self.assertEqual(len(node.getNormalChilds()), 0) childNode1 = Node() childNode2 = Node() node.extend([childNode1, childNode2]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 2) childNode3 = Node() node.extend([childNode3]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 3) node.extend([]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 3) with self.assertRaises(TypeError): node.extend([None]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 3) with self.assertRaises(TypeError): node.append([object]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 3) with self.assertRaises(TypeError): node.append(["a string is not a node object"]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 3) with self.assertRaises(MultipleParentsError): node.extend([childNode1]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 3) childNode4 = Node() childNode5 = Node() with self.assertRaises(MultipleParentsError): node.extend([childNode4, childNode5, childNode5]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertIn(childNode3, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(childNode3.getParent(), node) self.assertEqual(childNode4.getParent(), None) self.assertEqual(childNode5.getParent(), None) self.assertEqual(len(node.getNormalChilds()), 3) def testRemove(self): node = Node() self.assertEqual(len(node.getNormalChilds()), 0) childNode1 = Node() childNode2 = Node() node.extend([childNode1, childNode2]) self.assertIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 2) node.remove(childNode1) self.assertNotIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), None) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) node.remove(childNode1) self.assertNotIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), None) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) with self.assertRaises(TypeError): node.remove([None]) self.assertNotIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), None) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) with self.assertRaises(TypeError): node.remove([object]) self.assertNotIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), None) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) with self.assertRaises(TypeError): node.remove(["a string is not a node object"]) self.assertNotIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), None) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) def testInsert(self): node = Node() self.assertEqual(len(node.getNormalChilds()), 0) childNode1 = Node() node.insert(childNode1) self.assertIn(childNode1, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) childNode2 = Node() node.insert(childNode2) self.assertIn(childNode1, childNode2.getNormalChilds()) self.assertNotIn(childNode1, node.getNormalChilds()) self.assertIn(childNode2, node.getNormalChilds()) self.assertEqual(childNode1.getParent(), childNode2) self.assertEqual(childNode2.getParent(), node) self.assertEqual(len(node.getNormalChilds()), 1) self.assertEqual(len(childNode1.getNormalChilds()), 0) self.assertEqual(len(childNode2.getNormalChilds()), 1) def testInsertWithManyChilds(self): node = Node() self.assertEqual(len(node.getNormalChilds()), 0) for i in range(0, 200): node.append(Node()) insertNode = Node() self.assertEqual(len(node.getNormalChilds()), 200) self.assertEqual(len(insertNode.getNormalChilds()), 0) node.insert(insertNode) self.assertEqual(len(node.getNormalChilds()), 1) self.assertEqual(len(insertNode.getNormalChilds()), 200) ================================================ FILE: KicadModTree/tests/test.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, import os import sys import unittest sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../")) from nodes import * # NOQA from datatypes import * # NOQA from moduletests import * # NOQA def run_tests(): unittest.main() if __name__ == '__main__': run_tests() ================================================ FILE: KicadModTree/util/__init__.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, ================================================ FILE: KicadModTree/util/geometric_util.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, import math from KicadModTree.Vector import * import copy class geometricLine(): r""" Handle the geometric side of lines :params: * *start* (``Vector2D``) -- start point of the line * *end* (``Vector2D``) -- end point of the line """ def __init__(self, **kwargs): if 'geometry' in kwargs: geometry = kwargs['geometry'] self.start_pos = Vector2D(geometry.start_pos) self.end_pos = Vector2D(geometry.end_pos) else: self.start_pos = Vector2D(kwargs['start']) self.end_pos = Vector2D(kwargs['end']) def copy(self): return geometricLine(geometry=self) def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.start_pos.rotate(angle=angle, origin=origin, use_degrees=use_degrees) self.end_pos.rotate(angle=angle, origin=origin, use_degrees=use_degrees) return self def translate(self, distance_vector): r""" Translate :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.start_pos += distance_vector self.end_pos += distance_vector return self def isPointOnSelf(self, point, tolerance=1e-7): r""" is the given point on this line :params: * *point* (``Vector2D``) The point to be checked * *tolerance* (``float``) tolerance used to determine if the point is on the element default: 1e-7 """ ll, la = (self.end_pos - self.start_pos).to_polar() pl, pa = (point - self.start_pos).to_polar() return abs(la - pa) < tolerance and pl <= ll def sortPointsRelativeToStart(self, points): r""" sort given points releative to start point :params: * *points* (``[Vector2D]``) itterable of points """ if len(points) < 2: return points if len(points) > 2: raise NotImplementedError("Sorting for more than 2 points not supported") if self.start_pos.distance_to(points[0]) < self.start_pos.distance_to(points[1]): return points else: return [points[1], points[0]] def cut(self, *other): r""" cut line with given other element :params: * *other* (``Line``, ``Circle``, ``Arc``) cut the element on any intersection with the given geometric element """ ip = BaseNodeIntersection.intersectTwoNodes(self, *other) cp = [] for p in ip: if self.isPointOnSelf(p): cp.append(p) sp = self.sortPointsRelativeToStart(cp) sp.insert(0, self.start_pos) sp.append(self.end_pos) r = [] for i in range(len(sp)-1): r.append(geometricLine(start=sp[i], end=sp[i+1])) return r def to_homogeneous(self): r""" Get homogeneous representation of the line """ p1 = self.start_pos.to_homogeneous() p2 = self.end_pos.to_homogeneous() return p1.cross_product(p2) def __iter__(self): yield self.start_pos yield self.end_pos def __len__(self): return 2 def __getitem__(self, key): if key == 0 or key == 'start': return self.start_pos if key == 1 or key == 'end': return self.end_pos raise IndexError('Index {} is out of range'.format(key)) def __setitem__(self, key, item): if key == 0 or key == 'start': self.start_pos = item elif key == 1 or key == 'end': self.end_pos = item else: raise IndexError('Index {} is out of range'.format(key)) class geometricCircle(): r"""Handle the geometric side of circles :params: * *center* (``Vector2D``) -- center of the circle * *radius* (``float``) -- radius of the circle """ def __init__(self, center, radius): self.center_pos = Vector2D(center) self.radius = float(radius) def getRadius(self): return self.radius def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.center_pos.rotate(angle=angle, origin=origin, use_degrees=use_degrees) return self def translate(self, distance_vector): r""" Translate :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.center_pos += distance_vector return self def isPointOnSelf(self, point, tolerance=1e-7): r""" is the given point on this circle :params: * *point* (``Vector2D``) The point to be checked * *tolerance* (``float``) tolerance used to determine if the point is on the element default: 1e-7 """ rad_p, ang_p = Vector2D(point).to_polar(origin=self.center_pos) return abs(self.radius - rad_p) < tolerance def sortPointsRelativeToStart(self, points): r""" sort given points releative to start point :params: * *points* (``[Vector2D]``) itterable of points """ pass def cut(self, *other): r""" cut line with given other element :params: * *other* (``Line``, ``Circle``, ``Arc``) cut the element on any intersection with the given geometric element """ raise NotImplemented("cut for circles not yet implemented") # re use arc implementation with angle set to 360 deg # and start point set to 0 deg (polar) def __iter__(self): yield self.center_pos def __len__(self): return 1 def __getitem__(self, key): if key == 0 or key == 'center': return self.center_pos raise IndexError('Index {} is out of range'.format(key)) def __setitem__(self, key, item): if key == 0 or key == 'center': self.center_pos = item else: raise IndexError('Index {} is out of range'.format(key)) class geometricArc(): r""" Handle the geometric side of arcs :params: * *center* (``Vector2D``) -- center of arc * *start* (``Vector2D``) -- start point of arc * *midpoint* (``Vector2D``) -- alternative to start point point is on arc and defines point of equal distance to both arc ends arcs of this form are given as midpoint, center plus angle * *end* (``Vector2D``) -- alternative to angle arcs of this form are given as start, end and center * *angle* (``float``) -- angle of arc """ def __init__(self, **kwargs): if 'geometry' in kwargs: geometry = kwargs['geometry'] self.center_pos = Vector2D(geometry.center_pos) self.start_pos = Vector2D(geometry.start_pos) self.angle = float(geometry.angle) elif 'center' in kwargs: if 'angle' in kwargs: self._initFromCenterAndAngle(**kwargs) elif 'end' in kwargs: self._initFromCenterAndEnd(**kwargs) else: raise KeyError('Arcs defined with center point must define either an angle or endpoint') else: raise NotImplementedError('3 point arcs are not implemented, center is always required.') @staticmethod def normalizeAngle(angle): a = angle % (2*360) if a > 360: a -= 2*360 return a def _initAngle(self, angle): self.angle = geometricArc.normalizeAngle(angle) def _initFromCenterAndAngle(self, **kwargs): self.center_pos = Vector2D(kwargs['center']) self._initAngle(kwargs['angle']) if 'start' in kwargs: self.start_pos = Vector2D(kwargs['start']) elif 'midpoint' in kwargs: mp_r, mp_a = Vector2D(kwargs['midpoint']).to_polar( origin=self.center_pos, use_degrees=True) self.start_pos = Vector2D.from_polar( radius=mp_r, angle=mp_a-self.angle/2, origin=self.center_pos, use_degrees=True) else: raise KeyError('Arcs defined with center and angle must either define the start or midpoint.') def _initFromCenterAndEnd(self, **kwargs): self.center_pos = Vector2D(kwargs['center']) if 'start' in kwargs: self.start_pos = Vector2D(kwargs['start']) sp_r, sp_a = self.start_pos.to_polar( origin=self.center_pos, use_degrees=True) ep_r, ep_a = Vector2D(kwargs['end']).to_polar( origin=self.center_pos, use_degrees=True) if abs(sp_r - ep_r) > 1e-7: warnings.warn( """Start and end point are not an same arc. Extended line from center to end point used to determine angle.""" ) self._initAngle(ep_a - sp_a) if kwargs.get('long_way', False): if abs(self.angle) < 180: self.angle = -math.copysign((360-abs(self.angle)), self.angle) if self.angle == -180: self.angle = 180 else: if abs(self.angle) > 180: self.angle = -math.copysign((abs(self.angle) - 360), self.angle) if self.angle == 180: self.angle = -180 else: raise KeyError('Arcs defined with center and endpoint must define the start point.') def rotate(self, angle, origin=(0, 0), use_degrees=True): r""" Rotate around given origin :params: * *angle* (``float``) rotation angle * *origin* (``Vector2D``) origin point for the rotation. default: (0, 0) * *use_degrees* (``boolean``) rotation angle is given in degrees. default:True """ self.center_pos.rotate(angle=angle, origin=origin, use_degrees=use_degrees) self.start_pos.rotate(angle=angle, origin=origin, use_degrees=use_degrees) return self def translate(self, distance_vector): r""" Translate :params: * *distance_vector* (``Vector2D``) 2D vector defining by how much and in what direction to translate. """ self.center_pos += distance_vector self.start_pos += distance_vector return self def getRadius(self): r, a = (self.start_pos - self.center_pos).to_polar() return r def getStartPoint(self): return Vector2D(self.start_pos) def getMidPoint(self): return Vector2D(self.start_pos).rotate(self.angle/2, origin=self.center_pos) def getEndPoint(self): return Vector2D(self.start_pos).rotate(self.angle, origin=self.center_pos) def setRadius(self, radius): rad_s, ang_s = self.start_pos.to_polar(origin=self.center_pos) self.start_pos = Vector2D.from_polar(radius=radius, angle=ang_s, origin=self.center_pos) return self def _calulateEndPos(self): radius, angle = self.start_pos.to_polar( origin=self.center_pos, use_degrees=True) return Vector2D.from_polar( radius=radius, angle=angle+self.angle, origin=self.center_pos, use_degrees=True) def _toLocalCoordinates(self, point): rad_s, ang_s = self.start_pos.to_polar(origin=self.center_pos) rad_p, ang_p = Vector2D(point).to_polar(origin=self.center_pos) ang_p_s = (ang_p - ang_s) % 360 if self.angle < 0: ang_p_s -= 360 return (rad_p, ang_p_s) def _compareAngles(self, a1, a2, tolerance=1e-7): r""" compare which of the two angles given in the local coordinate system :params: * *a1* (``float``) angle 1 * *a2* (``float``) angle 2 * *tolerance* (``float``) tolerance used to determine if the point is on the element default: 1e-7 :return: * -1: angle 1 is closer to start * 0: both are of equal distance * 1: angle 2 is closer to start """ if abs(a1-a2) < tolerance: return 0 if self.angle < 0: if a1 < a2: return 1 else: if a1 > a2: return 1 return -1 def isPointOnSelf(self, point, tolerance=1e-7): r""" is the given point on this arc :params: * *point* (``Vector2D``) The point to be checked * *tolerance* (``float``) tolerance used to determine if the point is on the element default: 1e-7 """ rad_p, ang_p_s = self._toLocalCoordinates(point) rad_s, ang_s = self.start_pos.to_polar(origin=self.center_pos) # rotate to local coordinate system (start point is at 0 degree) ang_e_s = self.angle return self._compareAngles(ang_p_s, ang_e_s) == -1 and abs(rad_s - rad_p) < tolerance def sortPointsRelativeToStart(self, points): r""" sort given points releative to start point :params: * *points* (``[Vector2D]``) itterable of points """ if len(points) > 2: raise NotImplementedError("Sorting for more than 2 points not supported") ps = [] for p in points: ps.append(self._toLocalCoordinates(p)) if len(points) < 2: return ps if self._compareAngles(ps[0][1], ps[1][1]) == 1: return [ps[1], ps[0]] else: return ps def cut(self, *other): r""" cut line with given other element :params: * *other* (``Line``, ``Circle``, ``Arc``) cut the element on any intersection with the given geometric element """ ip = BaseNodeIntersection.intersectTwoNodes(self, *other) cp = [] for p in ip: if self.isPointOnSelf(p): cp.append(p) sp = self.sortPointsRelativeToStart(cp) sp.insert(0, (self.getRadius(), 0)) sp.append(self._toLocalCoordinates(self._calulateEndPos())) r = [] for i in range(len(sp)-1): r.append(geometricArc( center=self.center_pos, start=Vector2D(self.start_pos).rotate(sp[i][1], origin=self.center_pos), angle=sp[i+1][1]-sp[i][1] )) return r def __iter__(self): yield self.center_pos yield self.start_pos def __len__(self): return 2 def __getitem__(self, key): if key == 0 or key == 'center': return self.center_pos if key == 1 or key == 'start': return self.start_pos raise IndexError('Index {} is out of range'.format(key)) def __setitem__(self, key, item): if key == 0 or key == 'center': self.center_pos = item if key == 1 or key == 'start': return self.start_pos else: raise IndexError('Index {} is out of range'.format(key)) class BaseNodeIntersection(): @staticmethod def intersectTwoNodes(*nodes): import KicadModTree.nodes.base.Line if len(nodes) < 2 or len(nodes) > 3: raise KeyError("intersectTwoNodes expects two node objects or a node and two vectors") circles = [] lines = [] vectors = [] for n in nodes: if hasattr(n, 'getRadius') and hasattr(n, 'center_pos'): circles.append(n) elif hasattr(n, 'end_pos') and hasattr(n, 'start_pos'): lines.append(n) else: vectors.append(n) if len(vectors) == 2: lines.append(Line(start=vectors[0], end=vectors[1])) if len(lines) == 2: return BaseNodeIntersection.intersectTwoLines(*lines) if len(circles) == 2: raise NotImplementedError('intersection between circles is not supported') if len(lines) == 1 and len(circles) == 1: return BaseNodeIntersection.intersectLineWithCircle(lines[0], circles[0]) print(lines) print(circles) raise NotImplementedError('unsupported combination of parameter types') @staticmethod def intersectTwoLines(line1, line2): # we use homogeneous coordinates here. l1 = line1.to_homogeneous() l2 = line2.to_homogeneous() ip = l1.cross_product(l2) if ip.z == 0: return [] return [Vector2D.from_homogeneous(ip)] @staticmethod def intersectLineWithCircle(line, circle): # from http://mathworld.wolfram.com/Circle-LineIntersection.html # Equations are for circle center on (0, 0) so we translate everything # to the origin (well the line anyways as we do only need the radius of the circle) lt = line.copy().translate(-circle.center_pos) d = lt.end_pos - lt.start_pos dr = math.hypot(d.x, d.y) D = lt.start_pos.x*lt.end_pos.y - lt.end_pos.x*lt.start_pos.y discriminant = circle.getRadius()**2 * dr**2 - D**2 intersection = [] if discriminant < 0: return intersection def calcPoint(x): return Vector2D({ 'x': (D*d.y + x*math.copysign(1, d.y)*d.x*math.sqrt(discriminant))/dr**2, 'y': (-D*d.x + x*abs(d.y)*math.sqrt(discriminant))/dr**2 }) + circle.center_pos intersection.append(calcPoint(1)) if discriminant == 0: return intersection intersection.append(calcPoint(-1)) return intersection ================================================ FILE: KicadModTree/util/kicad_util.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, import time import re def formatFloat(val): ''' return well formated float ''' result = ('%f' % val).rstrip('0').rstrip('.') if result == '-0': result = '0' return result def lispString(string): ''' add quotation marks to string, when it include a white space or is empty ''' if type(string) is not str: string = str(string) if len(string) == 0 or re.match(".*\s.*", string): return '"{}"'.format(string.replace('"', '\\"')) # escape text return string def lispTokenizer(input): ''' Convert a string of characters into a list of tokens. ''' input = input.replace('(', ' ( ').replace(')', ' ) ') # split input, including whitespaces base_tokens = re.split(r'(\s+)', input) tokens = [] in_string = False for token in base_tokens: if not in_string and token.isspace(): continue if len(token) == 0: continue if token[0] == '"': if in_string: tokens[-1] += token[1:] in_string = False else: tokens.append(token[1:]) in_string = True elif token[-1] == '"': if in_string: tokens[-1] += token[:-1] in_string = False else: tokens.append(token[:-1]) in_string = True else: if in_string: tokens[-1] += token else: tokens.append(token) if in_string: raise RuntimeError("missing closing quotation mark") # TOOD: remove invalid spaces from quotation (when having brackets inside) return tokens def parseLispString(input): syntax_tree = [] current_node = syntax_tree scope = [syntax_tree] for token in lispTokenizer(input): if token == "(": scope.append([]) current_node.append(scope[-1]) current_node = scope[-1] elif token == ")": if len(scope) <= 1: raise RuntimeError("missing opening brackets") scope.pop() current_node = scope[-1] else: current_node.append(token) if len(scope) > 1: raise RuntimeError("missing closing brackets") if len(syntax_tree) == 1: syntax_tree = syntax_tree[0] return syntax_tree class SexprSerializer(object): ''' Converts a nested python list into a sexpr syntax which can be parsed by KiCad ''' NEW_LINE = object def __init__(self, sexpr): ''' :param sexpr: A list of lists and primitive values representing the file ''' self.sexpr = sexpr def primitive_to_string(self, primitive): pType = type(primitive) if pType is int: return str(primitive) elif pType is float: return formatFloat(primitive) elif pType is str: return lispString(primitive) else: raise RuntimeError("unexpected type: {}".format(pType)) def sexpr_to_string(self, sexpr, prefix=None): if prefix is None: prefix = "" serial_string = "(" # see: https://stackoverflow.com/questions/3190706/nonlocal-keyword-in-python-2-x loop_ctrl = {'first': True, 'indentation': False} def get_separator(): if loop_ctrl['first']: loop_ctrl['first'] = False return_str = "" else: return_str = " " if loop_ctrl['indentation']: return_str += " " loop_ctrl['indentation'] = False return return_str for attr in sexpr: if isinstance(attr, (tuple, list)): return_string = self.sexpr_to_string(attr, prefix + " ") if loop_ctrl['indentation']: return_string = return_string.replace('\n', '\n ') serial_string += get_separator() serial_string += return_string elif attr == SexprSerializer.NEW_LINE: serial_string += "\n" serial_string += prefix loop_ctrl['indentation'] = True else: serial_string += get_separator() serial_string += self.primitive_to_string(attr) serial_string += ")" return serial_string def __str__(self): ''' :return: A string which respresents the sexpr ''' return self.sexpr_to_string(self.sexpr) def parseTimestamp(timestamp): raise NotImplemented() return time.time() # TOOD def formatTimestamp(timestamp=None): if timestamp is None: timestamp = time.time() return "{timestamp:X}".format(timestamp=int(timestamp)) ================================================ FILE: KicadModTree/util/paramUtil.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016-2018 by Thomas Pointhuber, # (C) 2018 by Rene Poeschl, github @poeschlr from KicadModTree.Vector import * def toNumberArray(value, length=2, min_value=1, member_type=int): r""" Convert value into an array of given type with given length :param value: Possible input types: * numnber (int or float) -> returns array filled with copies of value * dict -> arreay created with values for keys 'x', 'y', 'z'. dict only supported for len 2 and 3 * list or tuple -> truncated to length * Vector -> truncated to lenght :param length: (``int``) -- default: 2 Defines the length of the resulting array :min_value: (``int``) -- default: 1 Defines the minimum alowed value (raise value error if too low) None -> No check :param mamber_type: (``type``) -- default: all members of the array will be converted to this type """ if type(value) in [int, float]: result = [value for i in range(length)] elif type(value) is dict: if length in [2, 3]: KEYS = ['x', 'y', 'z'] result = [value[KEYS[i]] for i in range(length)] else: raise TypeError('Dict only supported for length 2 or 3.') elif type(value) in [list, tuple]: if len(value) >= length: result = value[:length] elif type(value) in [Vector2D, Vector3D]: if len(value) < length: raise TypeError( 'Vector dimensions ({}) are too low. Must be at least {}'.format(len(value), length)) result = list(value) else: raise TypeError('Unsupported type: {}'.format(type(value))) result = [member_type(v) for v in result] if min_value is not None and isAnyLarger(result, min_value, False): raise ValueError( "At least one value in ({}) too small. Linit is {}.".format(result, min_value)) return result def toIntArray(value, length=2, min_value=1): r""" Convert value into an array of ints of given length :param value: Possible input types: * numnber (int or float) -> returns array filled with copies of value * dict -> arreay created with values for keys 'x', 'y', 'z'. dict only supported for len 2 and 3 * list or tuple -> truncated to length * Vector -> truncated to lenght :param length: (``int``) -- default: 2 Defines the length of the resulting array :min_value: (``int``) -- default: 1 Defines the minimum alowed value (raise value error if too low) None -> No check """ return toNumberArray(value, length, min_value, member_type=int) def toFloatArray(value, length=2, min_value=1): r""" Convert value into an array of floats of given length :param value: Possible input types: * numnber (int or float) -> returns array filled with copies of value * dict -> arreay created with values for keys 'x', 'y', 'z'. dict only supported for len 2 and 3 * list or tuple -> truncated to length * Vector -> truncated to lenght :param length: (``int``) -- default: 2 Defines the length of the resulting array :min_value: (``int``) -- default: 1 Defines the minimum alowed value (raise value error if too low) None -> No check """ return toNumberArray(value, length, min_value, member_type=float) def isAnyLarger(values, low_limits, must_be_larger=False): r"""Check if any value in the source array is larger than its respective limit :param value: (``itterable``) -- The values to check. :param low_limit: (``int``) Defines the minimum alowed value (raise value error if too low) None -> No check :param must_be_larger: (``bool``) -- default: True Defines if the number must be larger than the limit or if the limit is the minimum value. """ limits = toFloatArray(low_limits, len(values), min_value=None) for v, l in zip(values, limits): if v < l or (v <= l and must_be_larger): return True return False def toVectorUseCopyIfNumber(value, length=2, low_limit=None, must_be_larger=True): r""" Convert value into an vector of given dimension :param value: The value to convert. Supported types are all types allowed for vector constructor plus int/float. If int/float vector will be initialized with the correct number of copies. :param length: (2 or 3) -- default: 2 Defines the dimension of the resulting vector :param low_limit: (``int``) -- default: None Defines the minimum alowed value (raise value error if too low) None -> No check :param must_be_larger: (``bool``) -- default: True Defines if the number must be larger than the limit or if the limit is the minimum value. """ if type(value) in [int, float]: result = [value for i in range(length)] else: result = value if length == 2: result = Vector2D(result) elif length == 3: result = Vector3D(result) else: raise ValueError("length must be 2 or 3") if low_limit is not None and isAnyLarger(result, low_limit, must_be_larger): raise ValueError("One value in ({}) too small. Limit is {}.".format(result, low_limit)) return result def getOptionalNumberTypeParam( kwargs, param_name, default_value=None, low_limit=None, high_limit=None, allow_equal_limit=True): r""" Get a named parameter from packed dict and guarantee it is a number (float or int) :param param_name: The name of the parameter (=key) :param default_value: -- default: None The value to be used if the parameter is not in the dict :param low_limit: -- default: None The minimum allowable value :param high_limit: -- default: None The maximum allowable value :param allow_equal_limit: -- default: True Limits are included in range of allowable values (min <= x <= max if true else min < x < max) :param **kwargs: The parameters as packed dict """ val = kwargs.get(param_name, default_value) if val is not None: if type(val) not in [int, float]: raise TypeError('{} needs to be of type int or float'.format(param_name)) if low_limit is not None: if val < low_limit or (val == low_limit and not allow_equal_limit): raise ValueError( '{} with value {} violates the low limit of {}' .format(param_name, val, low_limit)) if high_limit is not None: if val > high_limit or (val == low_limit and not allow_equal_limit): raise ValueError( '{} with value {} violates the high limit of {}' .format(param_name, val, high_limit)) return val def round_to(value, base): r""" Round a value to a given base value :param value: The value to round :param base: The base value. The resulting value will be rounded to a multiple of it :return: The rounded value """ return round(value/base) * base ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program 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. This program 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 this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: README.md ================================================ ## :warning: 301 Moved Permanently Location: https://gitlab.com/kicad/libraries/kicad-footprint-generator --- This repository contains scripts to generate custom KiCAD footprints using python, and a framework which allows us to create custom KiCAD footprint. A big bunch of footprints of the KiCad library was developed using this framework. # KicadModTree **Licence:** GNU GPLv3+ **Maintainer:** Thomas Pointhuber [![Build Status](https://travis-ci.org/pointhi/kicad-footprint-generator.svg?branch=master)](https://travis-ci.org/pointhi/kicad-footprint-generator) [![Code Climate](https://codeclimate.com/github/pointhi/kicad-footprint-generator/badges/gpa.svg)](https://codeclimate.com/github/pointhi/kicad-footprint-generator) [![Documentation Status](https://readthedocs.org/projects/kicad-footprint-generator/badge/?version=latest)](http://kicad-footprint-generator.readthedocs.io/en/latest/?badge=latest) **Supports:** Python 2.7 and 3.3+ ## About I started drawing a bunch of similar footprints for KiCAD, like connectors which are mainly one base shape, and different amount of pins. To be able to update/improve those footprints quickly I decided to write my own footprint generator Framework, to allow simple creation of easy as well complex shapes. This is my second approach (the first one can be found in the git history). This solution should be able to be easy to use, to read and also be easy to expand with custom nodes. ## Overview This framework is mainly based on the idea of scripted CAD systems (for example OpenSCAD). This means, everything is a node, and can be structured like a tree. In other words, you can group parts of the footprint, and translate them in any way you want. Also cloning & co. is no problem anymore because of this concept. To be able to create custom Nodes, I separated the system in two parts. Base nodes, which represents simple structures and also be used by KiCAD itself, and specialized nodes which alter the behaviour of base nodes (for example positioning), or represent a specialized usage of base nodes (for example RectLine). When you serialize your footprint, the serialize command only has to handle base nodes, because all other nodes are based upon the base nodes. This allows us to write specialized nodes without worrying about the FileHandlers or other core systems. You simply create your special node, and the framework knows how to handle it seamlessly. Please look into the **[Documentation](http://kicad-footprint-generator.readthedocs.io/en/latest/)** for further details ``` KicadModTree - The KicadModTree framework which is used for footprint generation docs - Files required to generate a sphinx documentation scripts - scripts which are generating footprints based on this library ``` ## Development ### Install development Dependencies ```sh manage.sh update_dev_packages ``` ### run tests ```sh manage.sh tests ``` ## Example Script ```python from KicadModTree import * footprint_name = "example_footprint" # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, -3], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[1.5, 3], layer='F.Fab')) # create silscreen kicad_mod.append(RectLine(start=[-2, -2], end=[5, 2], layer='F.SilkS')) # create courtyard kicad_mod.append(RectLine(start=[-2.25, -2.25], end=[5.25, 2.25], layer='F.CrtYd')) # create pads kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[3, 0], size=[2, 2], drill=1.2, layers=Pad.LAYERS_THT)) # add model kicad_mod.append(Model(filename="example.3dshapes/example_footprint.wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # output kicad model file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('example_footprint.kicad_mod') ``` ## Usage Steps 1. Navigate into the `scripts` directory, and look for the type of footprint you would like to generate. For example, if you wish to generate an SMD inductor footprint, `cd` into `scripts/Inductor_SMD`. 2. Open the \*.yaml (or \*.yml) file in a text editor. Study a few of the existing footprint definitions to get an idea of how your new footprint entry should be structured. 3. Add your new footprint by inserting your own new section in the file. An easy way to do this is by simply copying an existing footprint definition, and modifying it to suit your part. Note: You may have to add or remove additional parameters that are not listed. 4. Save your edits and close the text editor. 5. Run the python script, passing the \*.yaml or (\*.yml) file as a parameter, e.g. `python3 Inductor_SMD.py Inductor_SMD.yml`. This will generate the \*.kicad_mod files for each footprint defined in the \*.yaml (or \*.yml). ================================================ FILE: docs/KicadModTree.nodes.base.rst ================================================ KicadModTree.nodes.base package =============================== Those nodes represent the primitives which we can use to create footprints. They are 1:1 mappings to the corresponding types used in .kicad_mod files. KicadModTree.nodes.base.Arc module ---------------------------------- .. automodule:: KicadModTree.nodes.base.Arc :members: :show-inheritance: KicadModTree.nodes.base.Circle module ------------------------------------- .. automodule:: KicadModTree.nodes.base.Circle :members: :show-inheritance: KicadModTree.nodes.base.Line module ----------------------------------- .. automodule:: KicadModTree.nodes.base.Line :members: :show-inheritance: KicadModTree.nodes.base.Model module ------------------------------------ .. automodule:: KicadModTree.nodes.base.Model :members: :show-inheritance: KicadModTree.nodes.base.Pad module ---------------------------------- .. automodule:: KicadModTree.nodes.base.Pad :members: :show-inheritance: KicadModTree.nodes.base.Polygon module ---------------------------------- .. automodule:: KicadModTree.nodes.base.Polygon :members: :show-inheritance: KicadModTree.nodes.base.Text module ----------------------------------- .. automodule:: KicadModTree.nodes.base.Text :members: :show-inheritance: ================================================ FILE: docs/KicadModTree.nodes.rst ================================================ KicadModTree.nodes package ========================== .. toctree:: KicadModTree.nodes.base KicadModTree.nodes.specialized KicadModTree.nodes.Footprint module ----------------------------------- .. automodule:: KicadModTree.nodes.Footprint :members: :undoc-members: :show-inheritance: KicadModTree.nodes.Node module ------------------------------ .. automodule:: KicadModTree.nodes.Node :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/KicadModTree.nodes.specialized.rst ================================================ KicadModTree.nodes.specialized package ====================================== To simpilfy the creation on footprints, we have special classes which are build onto the base nodes. special nodes are converted to base nodes when creating the footprint, and allows us to create much more complex shapes with as little boilerplate code as possible. KicadModTree.nodes.specialized.PolygoneLine module -------------------------------------------------- .. automodule:: KicadModTree.nodes.specialized.PolygoneLine :members: :show-inheritance: KicadModTree.nodes.specialized.RectLine module ---------------------------------------------- .. automodule:: KicadModTree.nodes.specialized.RectLine :members: :show-inheritance: KicadModTree.nodes.specialized.RectFill module ---------------------------------------------- .. automodule:: KicadModTree.nodes.specialized.RectFill :members: :show-inheritance: KicadModTree.nodes.specialized.FilledRect module ------------------------------------------------ .. automodule:: KicadModTree.nodes.specialized.FilledRect :members: :show-inheritance: KicadModTree.nodes.specialized.PadArray module ------------------------------------------------ .. automodule:: KicadModTree.nodes.specialized.PadArray :members: :show-inheritance: KicadModTree.nodes.specialized.Rotation module ---------------------------------------------- .. automodule:: KicadModTree.nodes.specialized.Rotation :members: :show-inheritance: KicadModTree.nodes.specialized.Translation module ------------------------------------------------- .. automodule:: KicadModTree.nodes.specialized.Translation :members: :show-inheritance: ================================================ FILE: docs/KicadModTree.rst ================================================ KicadModTree package ==================== .. toctree:: KicadModTree.nodes KicadModTree.util KicadModTree.FileHandler module ------------------------------- .. automodule:: KicadModTree.FileHandler :members: :undoc-members: :show-inheritance: KicadModTree.KicadFileHandler module ------------------------------------ .. automodule:: KicadModTree.KicadFileHandler :members: :undoc-members: :inherited-members: :show-inheritance: KicadModTree.ModArgparser module -------------------------------- .. automodule:: KicadModTree.ModArgparser :members: :undoc-members: :show-inheritance: KicadModTree.Vector module ------------------------- .. automodule:: KicadModTree.Vector :members: :undoc-members: :special-members: :show-inheritance: ================================================ FILE: docs/KicadModTree.util.rst ================================================ KicadModTree.util package ========================= KicadModTree.util.kicad_util module ----------------------------------- .. automodule:: KicadModTree.util.kicad_util :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/Makefile ================================================ # Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXPROJ = KicadModTree SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) ================================================ FILE: docs/conf.py ================================================ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # # KicadModTree documentation build configuration file, created by # sphinx-quickstart on Sun Feb 19 20:08:44 2017. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # import os import sys sys.path.insert(0, os.path.abspath('..')) # -- General configuration ------------------------------------------------ import sphinx_rtd_theme # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = 'KicadModTree' copyright = '2017, Thomas Pointhuber' author = 'Thomas Pointhuber' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '0.1' # The full version, including alpha/beta/rc tags. release = '0.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # #html_theme = 'alabaster' html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. htmlhelp_basename = 'KicadModTreedoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'KicadModTree.tex', 'KicadModTree Documentation', 'Thomas Pointhuber', 'manual'), ] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'kicadmodtree', 'KicadModTree Documentation', [author], 1) ] # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'KicadModTree', 'KicadModTree Documentation', author, 'KicadModTree', 'One line description of project.', 'Miscellaneous'), ] ================================================ FILE: docs/index.rst ================================================ .. KicadModTree documentation master file, created by sphinx-quickstart on Sun Feb 19 20:08:44 2017. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to KicadModTree's documentation! ======================================== KicadModTree is a framework which allows standalone creation KiCAD footprint. Overview ======== This framework is mainly based on the idea of scripted CAD systems (for example OpenSCAD). This means, everything is a node, and can be structured like a tree. In other words, you can group parts of the footprint, and translate them in any way you want. Also cloning & co. is no Problem anymore because of this concept. To be able to create custom Nodes, I separated the system in two parts. Base nodes, which represents simple structures and also be used by KiCAD itself, and specialized nodes which alter the behaviour of base nodes (for example positioning), or represent a specialized usage of base nodes (for example RectLine). When you serialize your footprint, the serialize command only has to handle base nodes, because all other nodes are based upon the base nodes. This allows us to write specialized nodes without worrying about the FileHandlers or other core systems. You simply create you special node, and the framework knows how to handle it seamlessly. Module Index ============ .. toctree:: :maxdepth: 4 :glob: KicadModTree Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` ================================================ FILE: manage.sh ================================================ #!/usr/bin/env bash if [[ "$OSTYPE" == "darwin"* ]]; then command -v greadlink >/dev/null 2>&1 || { echo >&2 "greadlink not found. Install using 'brew install coreutils'"; exit 1; } BASE_DIR="$(dirname "$(greadlink -f "$0")")" else BASE_DIR="$(dirname "$(readlink -f "$0")")" fi PYTHONPATH=$BASE_DIR KICADMODTREE_DIR="$BASE_DIR/KicadModTree" ACTION=$1 update_packages() { pip install --upgrade -r "$BASE_DIR/requirements.txt" } update_dev_packages() { update_packages pip install --upgrade -r "$BASE_DIR/requirements-dev.txt" } pep8_check() { echo '' echo '[!] Running pep8 check' pep8 --max-line-length=120 "$KICADMODTREE_DIR/" } flake8_check() { echo '' echo '[!] Running flake8 check' flake8 "$KICADMODTREE_DIR/" } unit_tests() { echo '' echo '[!] Running unit tests' python "$KICADMODTREE_DIR/tests/test.py" } py_test_coverage() { echo '[!] Running python test coverage' PYTHONPATH=`pwd` python -m nose2 -C --coverage "$KICADMODTREE_DIR" --coverage-report term-missing -s "$KICADMODTREE_DIR/tests" } tests() { set -e unit_tests pep8_check set +e } help() { [ -z "$1" ] || printf "Error: $1\n" echo '' echo "Searx manage.sh help Commands ======== help - This text pep8_check - pep8 validation flake8_check - flake8 validation unit_tests - Run unit tests py_test_coverage - Unit test coverage tests - Run all tests update_packages - Check & update production dependency changes update_dev_packages - Check & update development and production dependency changes " } #[ "$(command -V "$ACTION" | grep ' function$')" = "" ] \ # && help "action not found" \ # || $ACTION if [ -n "$(type -t $ACTION)" ] && [ "$(type -t $ACTION)" = function ]; then $ACTION else help "action not found" fi ================================================ FILE: requirements-dev.txt ================================================ pep8 flake8 unittest2 nose2 nose2-cov sphinx sphinx_rtd_theme ================================================ FILE: requirements.txt ================================================ pyyaml future ================================================ FILE: scripts/Battery/BatteryHolder.py ================================================ #!/usr/bin/env python3 import sys import os import re # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) # load scripts sys.path.append(os.path.join(sys.path[0], "..")) from KicadModTree import * from general.StandardBox import * def qfn(args): extraffablines = [] footprint_name = args["name"] description = args["description"] datasheet = args["description"] fptag = args["tags"] SmdTht = args["smd_tht"] at = args["at"] size = args["size"] pins = args["pins"] extratexts = args["extratexts"] dir3D = 'Battery.3dshapes' f = Footprint(footprint_name) file3Dname = "${KISYS3DMOD}/" + dir3D + "/" + footprint_name + ".wrl" words = footprint_name.split("_") if words[-1].lower().startswith('handsolder'): words[-1] = '' ff = '_'.join(words) file3Dname = "${KISYS3DMOD}/" + dir3D + "/" + ff + ".wrl" f.append(StandardBox(footprint=f, description=description, datasheet=datasheet, at=at, size=size, tags=fptag, SmdTht=SmdTht, extratexts=extratexts, pins=pins, file3Dname=file3Dname )) # # # file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(qfn) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("description", type=str, required=True) parser.add_parameter("datasheet", type=str, required=True) parser.add_parameter("tags", type=str, required=True) parser.add_parameter("smd_tht", type=str, required=False, default='tht') parser.add_parameter("at", type=list, required=True) parser.add_parameter("size", type=list, required=False) parser.add_parameter("pins", type=list, required=True) parser.add_parameter("extratexts", type=list, required=True) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Battery/BatteryHolder.yml ================================================ BatteryHolder_Bulgin_BX0033_1xPP3: description: "Bulgin Battery Holder, BX0033, Battery Type 1xPP3" datasheet: "http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf" tags: "Bulgin Battery Holder, BX0033, Battery Type 1xPP3" extratexts: [[-3.0, 0, "-", "F.SilkS", 1.0, 1.0]] at: [-1.7, 8.55] size: [58.7, 29.8] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.6], ["tht", "2", 0, -12.7, 3.0, 3.0, 1.6], ["npth", "", 10.7, -6.35, 3.0, 0, 3.0], ["npth", "", 24.7, -6.35, 3.0, 0, 3.0]] BatteryHolder_Bulgin_BX0034_1xAAA: description: "Bulgin Battery Holder, BX0034, Battery Type 1xAAA" datasheet: "http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf" tags: "Bulgin Battery Holder, BX0034, Battery Type 1xAAA" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-1.7, 8.65] size: [52.3, 17.3] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.6], ["tht", "2", 48.9, 0, 3.0, 3.0, 1.6], ["npth", "", 10.5, 0, 3.2, 0, 3.2], ["npth", "", 38.4, 0, 3.2, 0, 3.2]] BatteryHolder_Bulgin_BX0035_1xAA: description: "Bulgin Battery Holder, BX0035, Battery Type 1xAA (http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf)" datasheet: "Bulgin Battery Holder, BX0035, Battery Type 1xAA (http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf)" tags: "Bulgin Battery Holder, BX0035, Battery Type 1xAA" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-1.75, 10.80] size: [60.3, 21.6] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.6], ["tht", "2", 56.8, 0, 3.0, 3.0, 1.6], ["npth", "", 11.9, 0, 3.8, 0, 3.8], ["npth", "", 44.9, 0, 3.8, 0, 3.8]] BatteryHolder_Bulgin_BX0036_1xC: description: "Bulgin Battery Holder, BX0036, Battery Type 1xC" datasheet: "http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf" tags: "Bulgin Battery Holder, BX0036, Battery Type 1xC" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-1.75, 17.0] size: [59.1, 34.0] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.6], ["tht", "2", 55.6, 0, 3.0, 3.0, 1.6], ["npth", "", 11.9, 0, 3.8, 0, 3.8], ["npth", "", 43.7, 0, 3.8, 0, 3.8]] BatteryHolder_Bulgin_BX0037_1xD: description: "Bulgin Battery Holder, BX0037, Battery Type 1xD" datasheet: "http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf" tags: "Bulgin Battery Holder, BX0037, Battery Type 1xD" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-1.75, 20.95] size: [71.0, 41.9] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.6], ["tht", "2", 67.5, 0, 3.0, 3.0, 1.6], ["npth", "", 15.95, 0, 3.8, 0, 3.8], ["npth", "", 51.55, 0, 3.8, 0, 3.8]] BatteryHolder_Bulgin_BX0123_1xCR123: description: "Bulgin Battery Holder, BX0123, Battery Type 1xCR123" datasheet: "http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf" tags: "Bulgin Battery Holder, BX0123, Battery Type 1xCR123" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-1.75, 10.0] size: [41.3, 20.0] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.6], ["tht", "2", 37.8, 0, 3.0, 3.0, 1.6], ["npth", "", 10.425, 0, 3.2, 0, 3.2], ["npth", "", 27.375, 0, 3.2, 0, 3.2]] BatteryHolder_Keystone_1042_1x18650: description: "Keystone Battery Holder, 1042, Battery Type 1x18650" datasheet: "http://www.keyelco.com/product.cfm/product_id/918" tags: "Keystone Battery Holder, 1042, Battery Type 1x18650" extratexts: [[-49.0, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-43.205, 10.325] size: [86.41, 20.65] smd_tht: "smd" pins: [["smd", "1", -43.205, 0, 6.47, 6.47, 0.0], ["smd", "2", 43.205, 0, 6.47, 6.47, 0.0]] BatteryHolder_Keystone_2466_1xAAA: description: "Keystone Battery Holder, 2466, Battery Type 1xAAA" datasheet: "http://www.keyelco.com/product-pdf.cfm?p=1031" tags: "Keystone Battery Holder, 2466, Battery Type 1xAAA" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-2.645, 6.50] size: [49.99, 13.00] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.1], ["tht", "2", 44.70, 0, 3.0, 3.0, 1.1]] BatteryHolder_Keystone_2468_2xAAA: description: "Keystone Battery Holder, 2468, Battery Type 2xAAA" datasheet: "http://www.keyelco.com/product-pdf.cfm?p=1033" tags: "Keystone Battery Holder, 2468, Battery Type 2xAAA" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-2.865, 5.945] size: [52.98, 24.59] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.1], ["tht", "2", 0, -12.70, 3.0, 3.0, 1.1], ["npth", "", 8.64, -4, 3.45, 0, 3.45], ["npth", "", 38.61, -8, 3.45, 0, 3.45]] BatteryHolder_Keystone_2479_3xAAA: description: "Keystone Battery Holder, 2479, Battery Type 3xAAA" datasheet: "http://www.keyelco.com/product-pdf.cfm?p=1041" tags: "Keystone Battery Holder 2479 Battery Type 3xAAA" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-2.59, 6.995] size: [52.63, 37.49] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.1], ["tht", "2", 0, -12.70, 3.0, 3.0, 1.1], ["npth", "", 23.72, 0, 3.45, 0, 3.45], ["npth", "", 23.72, -23.50, 3.45, 0, 3.45]] BatteryHolder_MPD_BC2AAPC_2xAA: description: "Keystone Battery Holder, BC2AAPC, Battery Type 2xAA" datasheet: "http://www.memoryprotectiondevices.com/datasheets/BC2AAPC-datasheet.pdf" tags: "MPD Battery Holder, BC2AAPC, Battery Type 2xAA" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-2.84, 8.445] size: [58.00, 30.50] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.1], ["tht", "2", 0, -13.59, 3.0, 3.0, 1.1], ["npth", "", 26.16, -6.63, 3.56, 0, 3.56]] BatteryHolder_MPD_BC12AAPC_2xAA: description: "Keystone Battery Holder, BC12AAPC, Battery Type 2xAA" datasheet: "http://www.memoryprotectiondevices.com/datasheets/BC12AAPC-datasheet.pdf" tags: "MPD Battery Holder, BC12AAPC, Battery Type 2xAA" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-2.9, 8.1] size: [107.8, 16.20] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.1], ["tht", "2", 102.0, 0, 3.0, 3.0, 1.1], ["npth", "", 26.15, 4.75, 2.5, 0, 1.1], ["npth", "", 26.15, -4.75, 2.5, 0, 1.1], ["npth", "", 75.85, 4.75, 2.5, 0, 1.1], ["npth", "", 75.85, -4.75, 2.5, 0, 1.1]] BatteryHolder_MPD_BH-18650-PC: description: "Keystone Battery Holder, BH-18650, Battery Type 1x18650" datasheet: "http://www.memoryprotectiondevices.com/datasheets/BH-18650-PC-datasheet.pdf" tags: "MPD Battery Holder, BH-18650, Battery Type 1x18650" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-2.4, 10.45] size: [77.7, 20.9] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.57], ["tht", "2", 72.90, 0, 3.0, 3.0, 1.57], ["npth", "", 8.445, 0.0, 3.2, 0, 3.2], ["npth", "", 64.055, 0.0, 3.2, 0, 3.2]] BatteryHolder_MPD_BK-18650-PC2: description: "Keystone Battery Holder, BH-18650, Battery Type 1x18650" datasheet: "http://www.memoryprotectiondevices.com/datasheets/BK-18650-PC2-datasheet.pdf" tags: "MPD Battery Holder, BK-18650, Battery Type 1x18650" extratexts: [[-4.5, -0.05, "+", "F.SilkS", 3.0, 3.0]] at: [-2.23, 10.49] size: [76.96, 20.98] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.57], ["tht", "2", 72.90, 0, 3.0, 3.0, 1.57], ["npth", "", 8.445, 0.0, 3.2, 0, 3.2], ["npth", "", 64.055, 0.0, 3.2, 0, 3.2]] BatteryHolder_TruPower_BH-331P_3xAA: description: "Keystone Battery Holder BH-331P Battery Type 3xAA" datasheet: "https://static.rapidonline.com/pdf/18-2967_v1.pdf" tags: "Battery Holder BH-331P Battery Type 3xAA" extratexts: [[-4.5, 0.0, "+", "F.SilkS", 3.0, 3.0]] at: [-2.3, 9.15] size: [58.0, 48.3] pins: [["tht", "1", 0, 0, 3.0, 3.0, 1.2], ["tht", "2", 0, -12.8, 3.0, 3.0, 1.2], ["npth", "", 26.7, 0.0, 3.5, 0, 3.5], ["npth", "", 26.7, -30.0, 3.5, 0, 3.5]] ================================================ FILE: scripts/Battery/README.txt ================================================ Script to generate the battery holders To create all, type python BatteryHolder.py BatteryHolder.yml ================================================ FILE: scripts/Buttons_Switches/make_DIPSwitches.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_DIP import * if __name__ == '__main__': cwd= os.getcwd() try: os.mkdir("SMD") except: print("THT exists") try: os.mkdir("THT") except: print("THT exists") # common settings overlen_top=1.27 overlen_bottom=1.27 rm=2.54 ddrill=0.8 pad=[1.6,1.6] pad_large=[2.4,1.6] pad_smdsocket=[3.1,1.6] pad_smdsocket_small=[1.6,1.6] # DIP-switches: pins=[2,4,6,8,10,12,14,16,18,20,22,24] pinrow_distance = 7.62 package_width = 9.78 switch_width=4.06 switch_height=1.27 overlen_top = 2.36 overlen_bottom = 2.36 package_width_narrow = 6.7 switch_width_narrow = 3.62 switch_height_narrow = 1.27 overlen_top_narrow = 2.05 overlen_bottom_narrow = 2.05 pad_smd=[2.44,1.12] pinrow_distance_smd=8.61 pinrow_distance_smd_J=6.73 pad_smd_J=[2.16,1.12] switch_width_piano=1.8 switch_height_piano=1.5 package_width_piano=10.8 overlen_top_piano = 2.05 overlen_bottom_piano = 2.05 switchtype="SPST" for p in pins: os.chdir(cwd) os.chdir("THT") makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, switch_width, switch_height, 'Slide', False, [], webpage="e.g. https://www.ctscorp.com/wp-content/uploads/206-208.pdf",switchtype=switchtype) makeDIPSwitch(p, rm, pinrow_distance, package_width_narrow, overlen_top_narrow, overlen_bottom_narrow, ddrill, pad, switch_width_narrow, switch_height_narrow, 'Slide', False, ["LowProfile"], webpage="e.g. https://www.ctscorp.com/wp-content/uploads/209-210.pdf",switchtype=switchtype) makeDIPSwitch(p, rm, pinrow_distance, package_width_piano, overlen_top_piano, overlen_bottom_piano, ddrill, pad, switch_width_piano, switch_height_piano, 'Piano', False, [], webpage="",switchtype=switchtype) os.chdir(cwd) os.chdir("SMD") makeDIPSwitch(p, rm, pinrow_distance_smd, package_width_narrow, overlen_top_narrow, overlen_bottom_narrow, ddrill, pad_smd, switch_width_narrow, switch_height_narrow, 'Slide', True,["SMD","LowProfile"], 'Button_Switch_SMD', webpage="e.g. https://www.ctscorp.com/wp-content/uploads/219.pdf",switchtype=switchtype) makeDIPSwitch(p, rm, pinrow_distance_smd, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True,["SMD"], 'Button_Switch_SMD', webpage="e.g. https://www.ctscorp.com/wp-content/uploads/204.pdf",switchtype=switchtype) makeDIPSwitch(p, rm, pinrow_distance_smd_J, package_width_narrow, overlen_top_narrow, overlen_bottom_narrow, ddrill, pad_smd_J, switch_width_narrow, switch_height_narrow, 'Slide', True,["SMD","LowProfile","JPin"], 'Button_Switch_SMD', webpage="e.g. https://www.ctscorp.com/wp-content/uploads/219.pdf",switchtype=switchtype) pins=[4,6,8,10,12,14,16,18,20,22,24] switch_width_piano=1.14 switch_height_piano=1.52 package_width_piano=9.78 overlen_top_piano = (7.26-2.54)/2 overlen_bottom_piano = overlen_top_piano os.chdir(cwd) os.chdir("THT") for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width_piano, overlen_top_piano, overlen_bottom_piano, ddrill, pad, switch_width_piano, switch_height_piano, 'Piano', False, device_name="CTS_Series194-{0}MSTN".format(int(p/2)), webpage="https://www.ctscorp.com/wp-content/uploads/194-195.pdf",switchtype=switchtype) # Copal CVS DIP-switches (http://www.nidec-copal-electronics.com/e/catalog/switch/cvs.pdf): pins = [2, 4, 6, 8, 16] rm = 1 pinrow_distance = 5.9 package_width = 4.7 switch_width = 2 switch_height = 0.5 overlen_top = 1 overlen_bottom = 1 ddrill = 0 pad_smd = [1.2, 0.5] os.chdir(cwd) os.chdir("SMD") for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, [], "Button_Switch_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, [0.7, 0.7], 0.2, 0, webpage="http://www.nidec-copal-electronics.com/e/catalog/switch/cvs.pdf", device_name="Copal_CVS-{0:02}xB".format(int(p/2)),switchtype=switchtype) # Omron A6H DIP-switches (https://www.omron.com/ecb/products/pdf/en-a6h.pdf): pins = [4,8,12,16,20] rm = 1.27 pinrow_distance = 6.15 package_width = 4.5 switch_width = 3.2 switch_height = 0.5 overlen_top = 1.27 overlen_bottom = 1.27 ddrill = 0 pad_smd = [1.25, 0.76] os.chdir(cwd) os.chdir("SMD") for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, [], "Button_Switch_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, webpage="https://www.omron.com/ecb/products/pdf/en-a6h.pdf", device_name="Omron_A6H-{0}101".format(int(p/2)),switchtype=switchtype) # Omron A6S DIP-switches (http://omronfs.omron.com/en_US/ecb/products/pdf/en-a6s.pdf): pins = [2,4,6,8,10,12,14,16,18,20] rm = 2.54 pinrow_distance = 8.9 package_width = 6.2 switch_width = 3 switch_height = 1.1 overlen_top = 1.74 overlen_bottom = 1.74 ddrill = 0 pad_smd = [1.5, 1.1] os.chdir(cwd) os.chdir("SMD") for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, [], "Button_Switch_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, webpage="http://omronfs.omron.com/en_US/ecb/products/pdf/en-a6s.pdf", device_name="Omron_A6S-{0}10x".format(int(p/2)),switchtype=switchtype) # Copal CHS DIP-switches (http://www.nidec-copal-electronics.com/e/catalog/switch/chs.pdf): pins = [2, 4, 8, 12, 16, 20] rm = 1.27 pinrow_distance = 5.08 pinrow_distanceB = 7.62 package_width = 5.4 switch_width = 3 switch_height = 0.5 overlen_top = 1.27 overlen_bottom = 1.27 ddrill = 0 pad_smd = [1.6, 0.76] os.chdir(cwd) os.chdir("SMD") for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True,["SMD","JPin"], "Button_Switch_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, webpage="http://www.nidec-copal-electronics.com/e/catalog/switch/chs.pdf", device_name="Copal_CHS-{0:02}A".format(int(p/2)),switchtype=switchtype) makeDIPSwitch(p, rm, pinrow_distanceB, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True,["SMD"], "Button_Switch_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, webpage="http://www.nidec-copal-electronics.com/e/catalog/switch/chs.pdf", device_name="Copal_CHS-{0:02}B".format(int(p/2)),switchtype=switchtype) # KingTek DSHPxxTS DIP-switches (http://www.kingtek.net.cn/pic/201601201417455112.pdf): pins = [4,6,8,10,12,14,16,18,20] rm = 1.27 pinrow_distance = (8.89+6.35)/2 package_width = 5.4 switch_width = 2 switch_height = 0.8 overlen_top = (9.22-(5*1.27))/2 overlen_bottom = overlen_top ddrill = 0 pad_smd = [(8.89-6.35)/2, 0.76] os.chdir(cwd) os.chdir("SMD") for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, [], "Button_Switch_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, webpage="http://www.kingtek.net.cn/pic/201601201417455112.pdf", device_name="KingTek_DSHP{0:02}TS".format(int(p/2)),switchtype=switchtype) # KingTek DSHPxxTJ DIP-switches (http://www.kingtek.net.cn/pic/201601201446313350.pdf): pins = [4,6,8,10,12,14,16,18,20] rm = 1.27 pinrow_distance = (7.9+2.6)/2 package_width = 5.4 switch_width = 2 switch_height = 0.8 overlen_top = (6.88-(3*1.27))/2 overlen_bottom = overlen_top ddrill = 0 pad_smd = [(7.9-2.6)/2, 0.76] os.chdir(cwd) os.chdir("SMD") for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, ["JPin"], "Button_Switch_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, webpage="http://www.kingtek.net.cn/pic/201601201446313350.pdf", device_name="KingTek_DSHP{0:02}TJ".format(int(p/2)),switchtype=switchtype) os.chdir(cwd) ================================================ FILE: scripts/Buttons_Switches/rotary_coded_switch.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) from KicadModTree import * def rotary_coded_switch(args): footprint_name = args["name"] style = args["style"] datasheet = args["datasheet"] thru_hole = args["thru_hole"] pad_width = args["pad_width"] pad_height = args["pad_height"] pad_x_spacing = args["pad_x_spacing"] pad_y_spacing = args["pad_y_spacing"] gray = args["gray"] drill_size = args["drill_size"] pkg_width = args["pkg_width"] pkg_height = args["pkg_height"] f = Footprint(footprint_name) f.setDescription("4-bit rotary coded switch, " + style + ", " + datasheet) f.setTags("rotary switch bcd") if thru_hole: tech = "THT" else: tech = "SMD" f.setAttribute("smd") f.append(Model(filename="${KISYS3DMOD}/Buttons_Switches_" + tech + ".3dshapes/" + footprint_name + ".wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0.0, 0.0, 0.0])) wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 s = [1.0, 1.0] t = 0.15 silk_clearance = 0.2 crtYd = 0.25 d = [drill_size, drill_size] p = [pad_width, pad_height] if thru_hole: rows = [0, pad_y_spacing, 2 * pad_y_spacing] columns = [0, pad_x_spacing] else: rows = [-pad_y_spacing, 0, pad_y_spacing] columns = [-pad_x_spacing / 2, pad_x_spacing / 2] if gray: pins = ["1", "8", "C", "X", "4", "2"] else: pins = ["1", "8", "C", "C", "4", "2"] xCenter = (columns[0] + columns[1]) / 2 yCenter = rows[1] xLeft = xCenter - pkg_width / 2 xRight = xCenter + pkg_width / 2 yTop = yCenter - pkg_height / 2 yBottom = yCenter + pkg_height / 2 chamfer = 1.0 yRef = yTop - 1.25 yValue = yBottom + 1.25 boundLeft = xCenter - (pad_x_spacing + pad_width) / 2 boundRight = xCenter + (pad_x_spacing + pad_width) / 2 r = (pad_x_spacing - pad_width) / 2 - silk_clearance # Text f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s, thickness=t)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s, thickness=t)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=s, thickness=t)) # Fab f.append(PolygoneLine(polygone=[[xLeft + chamfer, yTop], [xRight, yTop], [xRight, yBottom], [xLeft, yBottom], [xLeft, yTop + chamfer], [xLeft + chamfer, yTop]], layer="F.Fab", width=wFab)) def tb_silkscreen(yOuter, yInner): f.append(PolygoneLine(polygone=[[xLeft - wSilkS, yInner], [xLeft - wSilkS, yOuter], [xRight + wSilkS, yOuter], [xRight + wSilkS, yInner]], layer="F.SilkS", width=wSilkS)) space = pad_height / 2 + silk_clearance tb_silkscreen(yTop - wSilkS, rows[0] - space) tb_silkscreen(yBottom + wSilkS, rows[2] + space) def compute_segment(row): return [rows[row] + space, rows[row + 1] - space] def lr_silkscreen(x, noMiddle): ys1 = compute_segment(0) ys2 = compute_segment(1) if noMiddle: ys = [[ys1[0], ys2[1]]] else: ys = [ys1, ys2] for seg in ys: f.append(Line(start=[x, seg[0]], end=[x, seg[1]], layer="F.SilkS", width=wSilkS)) lr_silkscreen(xLeft - wSilkS, False) lr_silkscreen(xRight + wSilkS, gray) margin = crtYd + wSilkS f.append(PolygoneLine(polygone=[[boundLeft - margin, yTop + chamfer], [boundLeft - margin, yTop - margin], [boundLeft + chamfer, yTop - margin]], layer="F.SilkS", width=wSilkS)) if thru_hole: f.append(Circle(center=[xCenter, yCenter], radius=r, layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xCenter, yCenter - r * 0.75], end=[xCenter, yCenter + r * 0.75], layer="F.SilkS", width=wSilkS)) f.append(PolygoneLine(polygone=[[xCenter - r * 0.5, yCenter - r * 0.25], [xCenter, yCenter - r * 0.75], [xCenter + r * 0.5, yCenter - r * 0.25]], layer="F.SilkS", width=wSilkS)) # Courtyard f.append(RectLine(start=[boundLeft - crtYd, yTop - crtYd], end=[boundRight + crtYd, yBottom + crtYd], layer="F.CrtYd", width=wCrtYd)) # Pins for row in range(0, 3): for col in range(0, 2): pin = pins[row * 2 + col] if pin == "1": padShape=Pad.SHAPE_RECT else: padShape=Pad.SHAPE_OVAL if pin != "X": if thru_hole: f.append(Pad(number=pin, type=Pad.TYPE_THT, shape=padShape, at=[columns[col], rows[row]], size=p, layers=Pad.LAYERS_THT, drill=d)) else: f.append(Pad(number=pin, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[columns[col], rows[row]], size=p, layers=Pad.LAYERS_SMT)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(rotary_coded_switch) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("style", type=str, required=True) parser.add_parameter("datasheet", type=str, required=False, default="https://www.nidec-copal-electronics.com/e/catalog/switch/sh-7000.pdf") parser.add_parameter("thru_hole", type=bool, required=False, default=False) parser.add_parameter("pad_width", type=float, required=False, default=2.5) parser.add_parameter("pad_height", type=float, required=False, default=1.0) parser.add_parameter("pad_x_spacing", type=float, required=False, default=6.5) parser.add_parameter("pad_y_spacing", type=float, required=False, default=2.54) parser.add_parameter("gray", type=bool, required=False, default=False) parser.add_parameter("drill_size", type=float, required=False, default=1.0) parser.add_parameter("pkg_width", type=float, required=False, default=7.1) parser.add_parameter("pkg_height", type=float, required=False, default=7.3) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Buttons_Switches/rotary_coded_switch.yml ================================================ Nidec_Copal_SH-7010A: style: J-hook pad_width: 2.5 pad_x_spacing: 6.5 Nidec_Copal_SH-7010B: style: gull wing pad_width: 3.0 pad_x_spacing: 8.0 Nidec_Copal_SH-7010C: style: through-hole thru_hole: true pad_height: 1.9 pad_width: 2.1 pad_x_spacing: 7.62 drill_size: 1.0 Nidec_Copal_SH-7040B: style: gull wing, Gray code gray: true pad_width: 3.0 pad_x_spacing: 8.0 ================================================ FILE: scripts/Buzzers_Beepers/buzzer_round_tht.py ================================================ #!/usr/bin/env python import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA def buzzer_round_tht(args): # some variables buzzer_center = args['pad_spacing'] / 2. buzzer_radius = args['diameter'] / 2. # init kicad footprint kicad_mod = Footprint(args['name']) kicad_mod.setDescription(args['datasheet']) kicad_mod.setTags("buzzer round tht") # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[buzzer_center, -buzzer_radius - 1], layer='F.SilkS')) kicad_mod.append(Text(type='user', text='%R', at=[buzzer_center, -buzzer_radius - 1], layer='F.Fab')) kicad_mod.append(Text(type='value', text=args['name'], at=[buzzer_center, buzzer_radius + 1], layer='F.Fab')) # create silkscreen kicad_mod.append(Circle(center=[buzzer_center, 0], radius=buzzer_radius + 0.1, layer='F.SilkS')) kicad_mod.append(Text(type='user', text='+', at=[0, -args['pad_size'] / 2 - 1], layer='F.SilkS')) kicad_mod.append(Text(type='user', text='+', at=[0, -args['pad_size']/2 - 1], layer='F.Fab')) # create fabrication layer kicad_mod.append(Circle(center=[buzzer_center, 0], radius=buzzer_radius, layer='F.Fab')) # create courtyard kicad_mod.append(Circle(center=[buzzer_center, 0], radius=buzzer_radius + args['courtyard'], layer='F.CrtYd')) # create pads kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=args['pad_size'], drill=args['hole_size'], layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[args['pad_spacing'], 0], size=args['pad_size'], drill=args['hole_size'], layers=Pad.LAYERS_THT)) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{}.kicad_mod'.format(args['name'])) if __name__ == '__main__': parser = ModArgparser(buzzer_round_tht) parser.add_parameter("name", type=str, required=True) # the root node of .yml files is parsed as name parser.add_parameter("datasheet", type=str, required=False) parser.add_parameter("courtyard", type=float, required=False, default=0.25) parser.add_parameter("diameter", type=float, required=True) parser.add_parameter("hole_size", type=float, required=True) parser.add_parameter("pad_size", type=float, required=True) parser.add_parameter("pad_spacing", type=float, required=True) parser.run() # now run our script which handles the whole part of parsing the files ================================================ FILE: scripts/Buzzers_Beepers/buzzer_round_tht_star_mictronics.csv ================================================ name,datasheet,diameter,hole_size,pad_size,pad_spacing MagneticBuzzer_StarMicronics_QMB-105,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,12,1,2,6.5 MagneticBuzzer_StarMicronics_QMB-108,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,12,1,2,6.5 MagneticBuzzer_StarMicronics_QMB-111,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,12,1,2,6.5 MagneticBuzzer_StarMicronics_QMX,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,12,1,2,6.6 MagneticBuzzer_StarMicronics_HGP,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,16,1.1,2,7.6 MagneticBuzzer_StarMicronics_RMX,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,16,1.1,2,7.6 MagneticBuzzer_StarMicronics_QMB,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,16,1.1,2,7.6 MagneticBuzzer_StarMicronics_TMX-F,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,25,1.2,2,10.2 MagneticBuzzer_StarMicronics_TMX-H,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,25,1.2,2,10.2 MagneticBuzzer_StarMicronics_TMB,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,12,1,2,7.6 MagneticBuzzer_StarMicronics_HMB,http://datasheet.octopart.com/HMB06-Star-Micronics-datasheet-514145.pdf,16,1.1,2,7.6 ================================================ FILE: scripts/Capacitors_SMD/CP_Elec_round.py ================================================ #!/usr/bin/env python import sys import os import argparse import yaml import math from collections import namedtuple sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA def create_footprint(name, configuration, **kwargs): kicad_mod = Footprint(name) # init kicad footprint datasheet = "" if 'datasheet' in kwargs: datasheet = kwargs['datasheet'] kicad_mod.setDescription(kwargs['description'] + " " + datasheet) kicad_mod.setTags('Capacitor Electrolytic') kicad_mod.setAttribute('smd') # set general values text_offset_y = kwargs['width'] / 2. + configuration['courtyard_offset']['default'] + 0.8 #silkscreen REF** silk_text_size = configuration['references'][0]['size'] silk_text_thickness = silk_text_size[0]*configuration['references'][0]['fontwidth'] kicad_mod.append(Text(type='reference', text='REF**', at=[0, -text_offset_y], layer='F.SilkS', size=[silk_text_size[0], silk_text_size[1]], thickness= silk_text_thickness)) #fab value fab_text_size = configuration['values'][0]['size'] fab_text_thickness = fab_text_size[0]*configuration['values'][0]['fontwidth'] kicad_mod.append(Text(type='value', text=name, at=[0, text_offset_y], layer='F.Fab', size=[fab_text_size[0], fab_text_size[1]], thickness= fab_text_thickness)) #fab REF** fab_text_size = kwargs['diameter']/5. fab_text_size = min(fab_text_size, configuration['references'][1]['size_max'][0]) fab_text_size = max(fab_text_size, configuration['references'][1]['size_min'][0]) fab_text_thickness = fab_text_size*configuration['references'][1]['thickness_factor'] kicad_mod.append(Text(type='user', text='%R', at=[0, 0], layer='F.Fab', size=[fab_text_size, fab_text_size], thickness= fab_text_thickness)) # create fabrication layer fab_x = kwargs['length'] / 2. fab_y = kwargs['width'] / 2. if kwargs['pin1_chamfer'] == 'auto': fab_edge = min(fab_x/2, fab_y/2, configuration['fab_pin1_marker_length']) else: fab_edge = kwargs['pin1_chamfer'] fab_x_edge = fab_x - fab_edge fab_y_edge = fab_y - fab_edge kicad_mod.append(Line(start=[fab_x, -fab_y], end=[fab_x, fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x_edge, -fab_y], end=[fab_x, -fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x_edge, fab_y], end=[fab_x, fab_y], layer='F.Fab', width=configuration['fab_line_width'])) if fab_edge > 0: kicad_mod.append(Line(start=[-fab_x, -fab_y_edge], end=[-fab_x, fab_y_edge], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x, -fab_y_edge], end=[-fab_x_edge, -fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x, fab_y_edge], end=[-fab_x_edge, fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=[0, 0], radius=kwargs['diameter']/2., layer='F.Fab', width=configuration['fab_line_width'])) #fab polarity marker fab_pol_size = kwargs['diameter']/10. fab_pol_wing = fab_pol_size/2. fab_pol_distance = kwargs['diameter']/2. - fab_pol_wing - configuration['fab_line_width'] fab_pol_pos_y = fab_text_size/2 + configuration['silk_pad_clearance'] + fab_pol_size fab_pol_pos_x = math.sqrt(fab_pol_distance*fab_pol_distance-fab_pol_pos_y*fab_pol_pos_y) fab_pol_pos_x = -fab_pol_pos_x fab_pol_pos_y = -fab_pol_pos_y kicad_mod.append(Line(start=[fab_pol_pos_x-fab_pol_wing, fab_pol_pos_y], end=[fab_pol_pos_x+fab_pol_wing, fab_pol_pos_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[fab_pol_pos_x, fab_pol_pos_y-fab_pol_wing], end=[fab_pol_pos_x, fab_pol_pos_y+fab_pol_wing], layer='F.Fab', width=configuration['fab_line_width'])) # create silkscreen fab_to_silk_offset = configuration['silk_fab_offset'] silk_x = kwargs['length'] / 2. + fab_to_silk_offset silk_y = kwargs['width'] / 2. + fab_to_silk_offset silk_y_start = kwargs['pad_width'] / 2. + configuration['silk_pad_clearance'] + configuration['silk_line_width']/2. silk_45deg_offset = fab_to_silk_offset*math.tan(math.radians(22.5)) silk_x_edge = fab_x - fab_edge + silk_45deg_offset silk_y_edge = fab_y - fab_edge + silk_45deg_offset kicad_mod.append(Line(start=[silk_x, silk_y], end=[silk_x, silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x, -silk_y], end=[silk_x, -silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x_edge, -silk_y], end=[silk_x, -silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x_edge, silk_y], end=[silk_x, silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) if silk_y_edge > silk_y_start: kicad_mod.append(Line(start=[-silk_x, silk_y_edge], end=[-silk_x, silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x, -silk_y_edge], end=[-silk_x, -silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x, -silk_y_edge], end=[-silk_x_edge, -silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x, silk_y_edge], end=[-silk_x_edge, silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) else: silk_x_cut = silk_x - (silk_y_start - silk_y_edge) # because of the 45 degree edge we can user a simple apporach silk_y_edge_cut = silk_y_start kicad_mod.append(Line(start=[-silk_x_cut, -silk_y_edge_cut], end=[-silk_x_edge, -silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x_cut, silk_y_edge_cut], end=[-silk_x_edge, silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) #silk polarity marker silk_pol_size = kwargs['diameter']/8. silk_pol_wing = silk_pol_size/2. silk_pol_pos_y = silk_y_start + silk_pol_size silk_pol_pos_x = silk_x + silk_pol_wing + configuration['silk_line_width']*2 silk_pol_pos_x = -silk_pol_pos_x silk_pol_pos_y = -silk_pol_pos_y kicad_mod.append(Line(start=[silk_pol_pos_x-silk_pol_wing, silk_pol_pos_y], end=[silk_pol_pos_x+silk_pol_wing, silk_pol_pos_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_pol_pos_x, silk_pol_pos_y-silk_pol_wing], end=[silk_pol_pos_x, silk_pol_pos_y+silk_pol_wing], layer='F.SilkS', width=configuration['silk_line_width'])) # create courtyard courtyard_offset = configuration['courtyard_offset']['default'] courtyard_x = kwargs['length'] / 2. + courtyard_offset courtyard_y = kwargs['width'] / 2. + courtyard_offset courtyard_pad_x = kwargs['pad_spacing'] / 2. + kwargs['pad_length'] + courtyard_offset courtyard_pad_y = kwargs['pad_width'] / 2. + courtyard_offset courtyard_45deg_offset = courtyard_offset*math.tan(math.radians(22.5)) courtyard_x_edge = fab_x - fab_edge + courtyard_45deg_offset courtyard_y_edge = fab_y - fab_edge + courtyard_45deg_offset courtyard_x_lower_edge = courtyard_x if courtyard_y_edge < courtyard_pad_y: courtyard_x_lower_edge = courtyard_x_lower_edge - courtyard_pad_y + courtyard_y_edge courtyard_y_edge = courtyard_pad_y #rounding courtyard_x = float(format(courtyard_x, ".2f")) courtyard_y = float(format(courtyard_y, ".2f")) courtyard_pad_x = float(format(courtyard_pad_x, ".2f")) courtyard_pad_y = float(format(courtyard_pad_y, ".2f")) courtyard_x_edge = float(format(courtyard_x_edge, ".2f")) courtyard_y_edge = float(format(courtyard_y_edge, ".2f")) courtyard_x_lower_edge = float(format(courtyard_x_lower_edge, ".2f")) # drawing courtyard kicad_mod.append(Line(start=[courtyard_x, -courtyard_y], end=[courtyard_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_x, -courtyard_pad_y], end=[courtyard_pad_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_pad_x, -courtyard_pad_y], end=[courtyard_pad_x, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_pad_x, courtyard_pad_y], end=[courtyard_x, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_x, courtyard_pad_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_edge, courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_edge, -courtyard_y], end=[courtyard_x, -courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) if fab_edge > 0: kicad_mod.append(Line(start=[-courtyard_x_lower_edge, courtyard_y_edge], end=[-courtyard_x_edge, courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_lower_edge, -courtyard_y_edge], end=[-courtyard_x_edge, -courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) if courtyard_y_edge > courtyard_pad_y: kicad_mod.append(Line(start=[-courtyard_x, -courtyard_y_edge], end=[-courtyard_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x, courtyard_pad_y], end=[-courtyard_x, courtyard_y_edge], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_lower_edge, -courtyard_pad_y], end=[-courtyard_pad_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_pad_x, -courtyard_pad_y], end=[-courtyard_pad_x, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_pad_x, courtyard_pad_y], end=[-courtyard_x_lower_edge, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) # all pads have this kwargs, so we only write them once pad_kwargs = {'type': Pad.TYPE_SMT, 'shape': Pad.SHAPE_RECT, 'layers': ['F.Cu', 'F.Mask', 'F.Paste']} # create pads x_pad_spacing = kwargs['pad_spacing'] / 2. + kwargs['pad_length'] / 2. kicad_mod.append(Pad(number= 1, at=[-x_pad_spacing, 0], size=[kwargs['pad_length'], kwargs['pad_width']], **pad_kwargs)) kicad_mod.append(Pad(number= 2, at=[x_pad_spacing, 0], size=[kwargs['pad_length'], kwargs['pad_width']], **pad_kwargs)) lib_name ='Capacitor_SMD' # add model modelname = name.replace("_HandSoldering", "") kicad_mod.append(Model(filename="{model_prefix:s}{lib_name:s}.3dshapes/{name:s}.wrl".format(model_prefix=configuration['3d_model_prefix'], lib_name=lib_name, name=modelname), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # write file output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) def parse_and_execute_yml_file(filepath, configuration): with open(filepath, 'r') as stream: try: yaml_parsed = yaml.safe_load(stream) for footprint in yaml_parsed: print("generate {name}.kicad_mod".format(name=footprint)) create_footprint(footprint, configuration , **yaml_parsed.get(footprint)) except yaml.YAMLError as exc: print(exc) if __name__ == "__main__": parser = argparse.ArgumentParser(description='Parse *.kicad_mod.yml file(s) and create matching footprints') parser.add_argument('files', metavar='file', type=str, nargs='+', help='yml-files to parse') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../tools/global_config_files/config_KLCv3.0.yaml') #parser.add_argument('-v', '--verbose', help='show more information when creating footprint', action='store_true') # TODO: allow writing into sub file args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) for filepath in args.files: parse_and_execute_yml_file(filepath, configuration) ================================================ FILE: scripts/Capacitors_SMD/CP_Elec_round.yaml ================================================ #CP_Elec_6.3x5.8: # body_length: # nominal: 6.6 # body_width: # nominal: 6.6 # body_height: # nominal: 5.8 # body_diameter: # nominal: 6.3 # pad_width: 1.9 # pin1_chamfer: 'auto' # pad_length: 3.5 # pad_spacing: 1.6 # https://industrial.panasonic.com/cdbs/www-data/pdf/AAB8000/AAB8000COL60.pdf # broken link # https://industrial.panasonic.com/cdbs/www-data/pdf/AAB8000/AAB8000COL10.pdf # pad sizes # https://www.vishay.com/docs/28395/150crz.pdf # http://www.nichicon.co.jp/english/products/pdfs/e-ch_ref.pdf # pad sizes # https://media.digikey.com/pdf/Data%20Sheets/Nichicon%20PDFs/ZD_Series.pdf # http://nichicon-us.com/english/products/pdfs/e-uzr.pdf # http://nichicon-us.com/english/products/pdfs/e-uzs.pdf # http://nichicon-us.com/english/products/pdfs/e-uwx.pdf # UCC, CDE, nor Rubycon datasheets are given above # 3x5.3 CP_Elec_3x5.4: extra_description: "Nichicon" body_length: nominal: 3.3 body_width: nominal: 3.3 body_height: nominal: 5.4 body_diameter: nominal: 3.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.2 pad_spacing: 0.8 CP_Elec_4x3: extra_description: "Nichicon" body_length: nominal: 4.3 body_width: nominal: 4.3 body_height: nominal: 3 body_diameter: nominal: 4.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.6 pad_spacing: 1 CP_Elec_4x3.9: extra_description: "Nichicon" body_length: nominal: 4.3 body_width: nominal: 4.3 body_height: nominal: 3.9 body_diameter: nominal: 4.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.6 pad_spacing: 1 CP_Elec_4x4.5: extra_description: "Nichicon" body_length: nominal: 4.3 body_width: nominal: 4.3 body_height: nominal: 4.5 body_diameter: nominal: 4.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.6 pad_spacing: 1 CP_Elec_4x5.3: extra_description: "Vishay" body_length: nominal: 4.3 body_width: nominal: 4.3 body_height: nominal: 5.3 body_diameter: nominal: 4.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.6 pad_spacing: 1 CP_Elec_4x5.4: extra_description: "Panasonic A5 / Nichicon" body_length: nominal: 4.3 body_width: nominal: 4.3 body_height: nominal: 5.4 body_diameter: nominal: 4.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.6 pad_spacing: 1 CP_Elec_4x5.7: extra_description: "United Chemi-Con" body_length: nominal: 4.3 body_width: nominal: 4.3 body_height: nominal: 5.7 body_diameter: nominal: 4.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.6 pad_spacing: 1 CP_Elec_4x5.8: extra_description: "Panasonic" body_length: nominal: 4.3 body_width: nominal: 4.3 body_height: nominal: 5.8 body_diameter: nominal: 4.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 2.6 pad_spacing: 1 CP_Elec_5x3: extra_description: "Nichicon" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 3.0 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x3.9: extra_description: "Nichicon" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 3.9 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x4.4: extra_description: "Panasonic B45" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 4.4 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x4.5: extra_description: "Nichicon" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 4.5 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x5.3: extra_description: "Nichicon" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 5.3 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x5.4: extra_description: "Nichicon" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 5.4 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x5.7: extra_description: "United Chemi-Con" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 5.7 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x5.8: extra_description: "Panasonic" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 5.8 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_5x5.9: extra_description: "Panasonic B6" body_length: nominal: 5.3 body_width: nominal: 5.3 body_height: nominal: 5.9 body_diameter: nominal: 5.0 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3 pad_spacing: 1.4 CP_Elec_6.3x3: extra_description: "Nichicon" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 3.0 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 1.9 CP_Elec_6.3x3.9: extra_description: "Nichicon" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 3.9 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 1.9 CP_Elec_6.3x4.5: extra_description: "Nichicon" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 4.5 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 1.9 CP_Elec_6.3x4.9: extra_description: "Panasonic C5" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 4.9 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 2.1 CP_Elec_6.3x5.2: extra_description: "United Chemi-Con" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 5.2 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 2.1 CP_Elec_6.3x5.3: extra_description: "Cornell Dubilier" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 5.3 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 2.1 CP_Elec_6.3x5.4: extra_description: "Panasonic C55" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 5.4 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 2.1 CP_Elec_6.3x5.4_Nichicon: extra_description: "Nichicon" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 5.4 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 1.9 CP_Elec_6.3x5.7: extra_description: "United Chemi-Con" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 5.7 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 1.9 CP_Elec_6.3x5.8: extra_description: "Nichicon" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 5.8 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 1.9 CP_Elec_6.3x5.9: extra_description: "Panasonic C6" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 5.9 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 2.1 CP_Elec_6.3x7.7: extra_description: "Nichicon" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 7.7 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 1.9 CP_Elec_6.3x9.9: extra_description: "Panasonic C10" body_length: nominal: 6.6 body_width: nominal: 6.6 body_height: nominal: 9.9 body_diameter: nominal: 6.3 pad_width: 1.6 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 2.1 CP_Elec_8x5.4: extra_description: "Nichicon" body_length: nominal: 8.3 body_width: nominal: 8.3 body_height: nominal: 5.4 body_diameter: nominal: 8.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4 pad_spacing: 2.1 CP_Elec_8x6.2: extra_description: "Nichicon" body_length: nominal: 8.3 body_width: nominal: 8.3 body_height: nominal: 6.2 body_diameter: nominal: 8.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4 pad_spacing: 2.1 CP_Elec_8x6.5: extra_description: "Rubycon" body_length: nominal: 8.3 body_width: nominal: 8.3 body_height: nominal: 6.5 body_diameter: nominal: 8.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4 pad_spacing: 2.1 CP_Elec_8x6.7: extra_description: "United Chemi-Con" body_length: nominal: 8.3 body_width: nominal: 8.3 body_height: nominal: 6.7 body_diameter: nominal: 8.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4 pad_spacing: 2.1 CP_Elec_8x6.9: extra_description: "Panasonic E7" body_length: nominal: 8.3 body_width: nominal: 8.3 body_height: nominal: 6.9 body_diameter: nominal: 8.0 pad_width: 1.9 pin1_chamfer: 'auto' pad_length: 4.15 pad_spacing: 2.8 CP_Elec_8x10: extra_description: "Nichicon" body_length: nominal: 8.3 body_width: nominal: 8.3 body_height: nominal: 10 body_diameter: nominal: 8.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 3.5 pad_spacing: 3 CP_Elec_8x10.5: extra_description: "Vishay 0810" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 8.5 body_width: nominal: 8.5 body_height: nominal: 10.5 body_diameter: nominal: 8.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4.4 pad_spacing: 3.0 CP_Elec_8x11.9: extra_description: "Panasonic E12" body_length: nominal: 8.3 body_width: nominal: 8.3 body_height: nominal: 11.9 body_diameter: nominal: 8.0 pad_width: 1.9 pin1_chamfer: 'auto' pad_length: 4.15 pad_spacing: 2.8 CP_Elec_10x7.7: extra_description: "Nichicon" body_length: nominal: 10.3 body_width: nominal: 10.3 body_height: nominal: 7.7 body_diameter: nominal: 10.0 pad_width: 1.9 pin1_chamfer: 'auto' pad_length: 4.4 pad_spacing: 4.3 CP_Elec_10x7.9: extra_description: "Panasonic F8" body_length: nominal: 10.3 body_width: nominal: 10.3 body_height: nominal: 7.9 body_diameter: nominal: 10.0 pad_width: 1.9 pin1_chamfer: 'auto' pad_length: 4.4 pad_spacing: 4.3 CP_Elec_10x10: extra_description: "Nichicon" body_length: nominal: 10.3 body_width: nominal: 10.3 body_height: nominal: 10.0 body_diameter: nominal: 10.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4 pad_spacing: 4 CP_Elec_10x10.5: extra_description: "Vishay 1010" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 10.5 body_width: nominal: 10.5 body_height: nominal: 10.5 body_diameter: nominal: 10.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4.4 pad_spacing: 4.0 CP_Elec_10x12.5: extra_description: "Vishay 1012" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 10.5 body_width: nominal: 10.5 body_height: nominal: 12.5 body_diameter: nominal: 10.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4.4 pad_spacing: 4.0 CP_Elec_10x12.6: extra_description: "Panasonic F12" body_length: nominal: 10.3 body_width: nominal: 10.3 body_height: nominal: 12.6 body_diameter: nominal: 10.0 pad_width: 1.9 pin1_chamfer: 'auto' pad_length: 4.4 pad_spacing: 4.3 CP_Elec_10x14.3: extra_description: "Vishay 1014" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 10.5 body_width: nominal: 10.5 body_height: nominal: 14.3 body_diameter: nominal: 10.0 pad_width: 2.5 pin1_chamfer: 'auto' pad_length: 4.4 pad_spacing: 4.0 # TODO: Vishay 12.5x14 # TODO: Vishay 12.5x16.5 CP_Elec_16x17.5: extra_description: "Vishay 1616" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 16.6 body_width: nominal: 16.6 body_height: nominal: 17.5 body_diameter: nominal: 16.0 pad_width: 9.6 pin1_chamfer: 'auto' pad_length: 7.8 pad_spacing: 4.7 CP_Elec_16x22: extra_description: "Vishay 1621" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 16.6 body_width: nominal: 16.6 body_height: nominal: 22.0 body_diameter: nominal: 16.0 pad_width: 9.6 pin1_chamfer: 'auto' pad_length: 7.8 pad_spacing: 4.7 CP_Elec_18x17.5: extra_description: "Vishay 1816" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 19.0 body_width: nominal: 19.0 body_height: nominal: 17.5 body_diameter: nominal: 18.0 pad_width: 9.6 pin1_chamfer: 'auto' pad_length: 8.8 pad_spacing: 4.7 CP_Elec_18x22: extra_description: "Vishay 1821" datasheet: "http://www.vishay.com/docs/28395/150crz.pdf" body_length: nominal: 19.0 body_width: nominal: 19.0 body_height: nominal: 22.0 body_diameter: nominal: 18.0 pad_width: 9.6 pin1_chamfer: 'auto' pad_length: 8.8 pad_spacing: 4.7 ######################Panasonic # #CP_Panasonic_Standard_B: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 4.3 # width: 4.3 # height: 5.8 # diameter: 4.0 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 2.5 # pad_spacing: 1.0 # #CP_Panasonic_Standard_B_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 4.3 # width: 4.3 # height: 5.8 # diameter: 4.0 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 3.5 # pad_spacing: 1.0 # #CP_Panasonic_Standard_C: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 5.3 # width: 5.3 # height: 5.8 # diameter: 5.0 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 2.8 # pad_spacing: 1.5 # #CP_Panasonic_Standard_C_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 5.3 # width: 5.3 # height: 5.8 # diameter: 5.0 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 3.8 # pad_spacing: 1.5 # #CP_Panasonic_Standard_D: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 6.6 # width: 6.6 # height: 5.8 # diameter: 6.3 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 3.2 # pad_spacing: 1.8 # #CP_Panasonic_Standard_D_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 6.6 # width: 6.6 # height: 5.8 # diameter: 6.3 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 4.2 # pad_spacing: 1.8 # #CP_Panasonic_Standard_E: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 8.3 # width: 8.3 # height: 6.2 # diameter: 8.0 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 4.0 # pad_spacing: 2.2 # #CP_Panasonic_Standard_E_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 8.3 # width: 8.3 # height: 6.2 # diameter: 8.0 # pad_width: 1.6 # pin1_chamfer: 'auto' # pad_length: 5.0 # pad_spacing: 2.2 # #CP_Panasonic_Standard_F: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 8.3 # width: 8.3 # height: 10.2 # diameter: 8.0 # pad_width: 2.0 # pin1_chamfer: 'auto' # pad_length: 4.0 # pad_spacing: 3.1 # #CP_Panasonic_Standard_F_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 8.3 # width: 8.3 # height: 10.2 # diameter: 8.0 # pad_width: 2.0 # pin1_chamfer: 'auto' # pad_length: 5.0 # pad_spacing: 3.1 # #CP_Panasonic_Standard_G: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 10.3 # width: 10.3 # height: 10.2 # diameter: 10.0 # pad_width: 2.0 # pin1_chamfer: 'auto' # pad_length: 4.1 # pad_spacing: 4.6 # #CP_Panasonic_Standard_G_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 10.3 # width: 10.3 # height: 10.2 # diameter: 10.0 # pad_width: 2.0 # pin1_chamfer: 'auto' # pad_length: 5.1 # pad_spacing: 4.6 # #CP_Panasonic_Standard_H: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 13.5 # width: 13.5 # height: 13.5 # diameter: 12.5 # pad_width: 2.0 # pin1_chamfer: 'auto' # pad_length: 5.7 # pad_spacing: 4.0 # #CP_Panasonic_Standard_H_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 13.5 # width: 13.5 # height: 13.5 # diameter: 12.5 # pad_width: 2.0 # pin1_chamfer: 'auto' # pad_length: 6.7 # pad_spacing: 4.0 # #CP_Panasonic_Standard_J: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 17.0 # width: 17.0 # height: 16.5 # diameter: 16.0 # pad_width: 2.5 # pin1_chamfer: 'auto' # pad_length: 6.5 # pad_spacing: 6.0 # #CP_Panasonic_Standard_J_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 17.0 # width: 17.0 # height: 16.5 # diameter: 16.0 # pad_width: 2.5 # pin1_chamfer: 'auto' # pad_length: 7.5 # pad_spacing: 6.0 # #CP_Panasonic_Standard_K: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 19.0 # width: 19.0 # height: 16.5 # diameter: 18.0 # pad_width: 2.5 # pin1_chamfer: 'auto' # pad_length: 7.5 # pad_spacing: 6.0 # #CP_Panasonic_Standard_K_HandSoldering: # extra_description: "Panasonic" # datasheet: "https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/DME0000COL48.pdf" # length: 19.0 # width: 19.0 # height: 16.5 # diameter: 18.0 # pad_width: 2.5 # pin1_chamfer: 'auto' # pad_length: 8.5 # pad_spacing: 6.0 ================================================ FILE: scripts/Capacitors_SMD/C_Elec_round.py ================================================ #!/usr/bin/env python import sys import os import argparse import yaml import math sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA sys.path.append(os.path.join(sys.path[0], "..", "tools")) # load parent path of tools from ipc_pad_size_calculators import * def create_footprint(name, configuration, **kwargs): kicad_mod = Footprint(name) # init kicad footprint datasheet = ", " + kwargs['datasheet'] if 'datasheet' in kwargs else "" description = "SMD capacitor, aluminum electrolytic" tags = 'capacitor electrolytic' if name[:2] == "C_": description += " nonpolar" tags += " nonpolar" if 'extra_description' in kwargs: description += ", " + kwargs['extra_description'] # ensure all provided dimensions are fully toleranced device_dimensions = { 'body_length': TolerancedSize.fromYaml(kwargs, base_name='body_length'), 'body_width': TolerancedSize.fromYaml(kwargs, base_name='body_width'), 'body_height': TolerancedSize.fromYaml(kwargs, base_name='body_height'), 'body_diameter': TolerancedSize.fromYaml(kwargs, base_name='body_diameter') } # for ease of use, capture nominal body and pad sizes body_size = { 'length': device_dimensions['body_length'].nominal, 'width': device_dimensions['body_width'].nominal, 'height': device_dimensions['body_height'].nominal, 'diameter': device_dimensions['body_diameter'].nominal } description += ", " + str(body_size['diameter']) + "x" + str(body_size['height']) + "mm" kicad_mod.setDescription(description + datasheet) kicad_mod.setTags(tags) kicad_mod.setAttribute('smd') # set general values text_offset_y = body_size['width'] / 2.0 + configuration['courtyard_offset']['default'] + 0.8 #silkscreen REF** silk_text_size = configuration['references'][0]['size'] silk_text_thickness = silk_text_size[0]*configuration['references'][0]['fontwidth'] kicad_mod.append(Text(type='reference', text='REF**', at=[0, -text_offset_y], layer='F.SilkS', size=[silk_text_size[0], silk_text_size[1]], thickness= silk_text_thickness)) #fab value fab_text_size = configuration['values'][0]['size'] fab_text_thickness = fab_text_size[0]*configuration['values'][0]['fontwidth'] kicad_mod.append(Text(type='value', text=name, at=[0, text_offset_y], layer='F.Fab', size=[fab_text_size[0], fab_text_size[1]], thickness= fab_text_thickness)) #fab REF** fab_text_size = body_size['diameter']/5.0 fab_text_size = min(fab_text_size, configuration['references'][1]['size_max'][0]) fab_text_size = max(fab_text_size, configuration['references'][1]['size_min'][0]) fab_text_thickness = fab_text_size*configuration['references'][1]['thickness_factor'] kicad_mod.append(Text(type='user', text='%R', at=[0, 0], layer='F.Fab', size=[fab_text_size, fab_text_size], thickness= fab_text_thickness)) # create pads # all pads have these properties pad_params = {'type': Pad.TYPE_SMT, 'layers': Pad.LAYERS_SMT, 'shape': Pad.SHAPE_RECT} # prefer IPC-7351C compliant rounded rectangle pads if not configuration['force_rectangle_pads']: pad_params['shape'] = Pad.SHAPE_ROUNDRECT pad_params['radius_ratio'] = 0.25 pad_params['maximum_radius'] = 0.25 # prefer calculating pads from lead dimensions per IPC # fall back to using pad sizes directly if necessary if ('lead_length' in kwargs) and ('lead_width' in kwargs) and ('lead_spacing' in kwargs): # gather IPC data (unique parameters for >= 10mm tall caps) ipc_density_suffix = '' if body_size['height'] < 10 else '_10mm' ipc_density = configuration['ipc_density'] ipc_data = ipc_defintions['ipc_spec_capae_crystal'][ipc_density + ipc_density_suffix] ipc_round_base = ipc_defintions['ipc_spec_capae_crystal']['round_base'] manf_tol = { 'F': configuration.get('manufacturing_tolerance', 0.1), 'P': configuration.get('placement_tolerance', 0.05) } # # fully tolerance lead dimensions; leads are dimensioned like SOIC so use gullwing calculator device_dimensions['lead_width'] = TolerancedSize.fromYaml(kwargs, base_name='lead_width') device_dimensions['lead_spacing'] = TolerancedSize.fromYaml(kwargs, base_name='lead_spacing') device_dimensions['lead_length'] = TolerancedSize.fromYaml(kwargs, base_name='lead_length') device_dimensions['lead_outside'] = TolerancedSize(maximum = device_dimensions['lead_spacing'].maximum + device_dimensions.get('lead_length').maximum * 2, minimum = device_dimensions['lead_spacing'].minimum + device_dimensions.get('lead_length').minimum * 2) Gmin, Zmax, Xmax = ipc_gull_wing(ipc_data, ipc_round_base, manf_tol, device_dimensions['lead_width'], device_dimensions['lead_outside'], lead_len=device_dimensions.get('lead_length')) pad_params['size'] = [(Zmax - Gmin) / 2.0, Xmax] x_pad_spacing = (Zmax + Gmin) / 4.0 elif ('pad_length' in kwargs) and ('pad_width' in kwargs) and ('pad_spacing' in kwargs): x_pad_spacing = kwargs['pad_spacing'] / 2.0 + kwargs['pad_length'] / 2.0 pad_params['size'] = [kwargs['pad_length'], kwargs['pad_width']] else: raise KeyError("Provide all three 'pad' or 'lead' properties ('_spacing', '_length', and '_width')") kicad_mod.append(Pad(number=1, at=[-x_pad_spacing, 0], **pad_params)) kicad_mod.append(Pad(number=2, at=[x_pad_spacing, 0], **pad_params)) # create fabrication layer fab_x = body_size['length'] / 2.0 fab_y = body_size['width'] / 2.0 if kwargs['pin1_chamfer'] == 'auto': fab_edge = min(fab_x/2.0, fab_y/2.0, configuration['fab_pin1_marker_length']) else: fab_edge = kwargs['pin1_chamfer'] fab_x_edge = fab_x - fab_edge fab_y_edge = fab_y - fab_edge kicad_mod.append(Line(start=[fab_x, -fab_y], end=[fab_x, fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x_edge, -fab_y], end=[fab_x, -fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x_edge, fab_y], end=[fab_x, fab_y], layer='F.Fab', width=configuration['fab_line_width'])) if fab_edge > 0: kicad_mod.append(Line(start=[-fab_x, -fab_y_edge], end=[-fab_x, fab_y_edge], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x, -fab_y_edge], end=[-fab_x_edge, -fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[-fab_x, fab_y_edge], end=[-fab_x_edge, fab_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=[0, 0], radius=body_size['diameter']/2.0, layer='F.Fab', width=configuration['fab_line_width'])) #fab polarity marker for polarized caps if name[:2].upper() == "CP": fab_pol_size = body_size['diameter']/10.0 fab_pol_wing = fab_pol_size/2.0 fab_pol_distance = body_size['diameter']/2.0 - fab_pol_wing - configuration['fab_line_width'] fab_pol_pos_y = fab_text_size/2.0 + configuration['silk_pad_clearance'] + fab_pol_size fab_pol_pos_x = math.sqrt(fab_pol_distance*fab_pol_distance-fab_pol_pos_y*fab_pol_pos_y) fab_pol_pos_x = -fab_pol_pos_x fab_pol_pos_y = -fab_pol_pos_y kicad_mod.append(Line(start=[fab_pol_pos_x-fab_pol_wing, fab_pol_pos_y], end=[fab_pol_pos_x+fab_pol_wing, fab_pol_pos_y], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[fab_pol_pos_x, fab_pol_pos_y-fab_pol_wing], end=[fab_pol_pos_x, fab_pol_pos_y+fab_pol_wing], layer='F.Fab', width=configuration['fab_line_width'])) # create silkscreen fab_to_silk_offset = configuration['silk_fab_offset'] silk_x = body_size['length'] / 2.0 + fab_to_silk_offset silk_y = body_size['width'] / 2.0 + fab_to_silk_offset silk_y_start = pad_params['size'][1] / 2.0 + configuration['silk_pad_clearance'] + configuration['silk_line_width']/2.0 silk_45deg_offset = fab_to_silk_offset*math.tan(math.radians(22.5)) silk_x_edge = fab_x - fab_edge + silk_45deg_offset silk_y_edge = fab_y - fab_edge + silk_45deg_offset kicad_mod.append(Line(start=[silk_x, silk_y], end=[silk_x, silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x, -silk_y], end=[silk_x, -silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x_edge, -silk_y], end=[silk_x, -silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x_edge, silk_y], end=[silk_x, silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) if silk_y_edge > silk_y_start: kicad_mod.append(Line(start=[-silk_x, silk_y_edge], end=[-silk_x, silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x, -silk_y_edge], end=[-silk_x, -silk_y_start], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x, -silk_y_edge], end=[-silk_x_edge, -silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x, silk_y_edge], end=[-silk_x_edge, silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) else: silk_x_cut = silk_x - (silk_y_start - silk_y_edge) # because of the 45 degree edge we can user a simple apporach silk_y_edge_cut = silk_y_start kicad_mod.append(Line(start=[-silk_x_cut, -silk_y_edge_cut], end=[-silk_x_edge, -silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-silk_x_cut, silk_y_edge_cut], end=[-silk_x_edge, silk_y], layer='F.SilkS', width=configuration['silk_line_width'])) #silk polarity marker if name[:2].upper() == "CP": silk_pol_size = body_size['diameter']/8.0 silk_pol_wing = silk_pol_size/2.0 silk_pol_pos_y = silk_y_start + silk_pol_size silk_pol_pos_x = silk_x + silk_pol_wing + configuration['silk_line_width']*2 silk_pol_pos_x = -silk_pol_pos_x silk_pol_pos_y = -silk_pol_pos_y kicad_mod.append(Line(start=[silk_pol_pos_x-silk_pol_wing, silk_pol_pos_y], end=[silk_pol_pos_x+silk_pol_wing, silk_pol_pos_y], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_pol_pos_x, silk_pol_pos_y-silk_pol_wing], end=[silk_pol_pos_x, silk_pol_pos_y+silk_pol_wing], layer='F.SilkS', width=configuration['silk_line_width'])) # create courtyard courtyard_offset = configuration['courtyard_offset']['default'] courtyard_x = body_size['length'] / 2.0 + courtyard_offset courtyard_y = body_size['width'] / 2.0 + courtyard_offset courtyard_pad_x = x_pad_spacing + pad_params['size'][0] / 2.0 + courtyard_offset courtyard_pad_y = pad_params['size'][1] / 2.0 + courtyard_offset courtyard_45deg_offset = courtyard_offset*math.tan(math.radians(22.5)) courtyard_x_edge = fab_x - fab_edge + courtyard_45deg_offset courtyard_y_edge = fab_y - fab_edge + courtyard_45deg_offset courtyard_x_lower_edge = courtyard_x if courtyard_y_edge < courtyard_pad_y: courtyard_x_lower_edge = courtyard_x_lower_edge - courtyard_pad_y + courtyard_y_edge courtyard_y_edge = courtyard_pad_y #rounding courtyard_x = float(format(courtyard_x, ".2f")) courtyard_y = float(format(courtyard_y, ".2f")) courtyard_pad_x = float(format(courtyard_pad_x, ".2f")) courtyard_pad_y = float(format(courtyard_pad_y, ".2f")) courtyard_x_edge = float(format(courtyard_x_edge, ".2f")) courtyard_y_edge = float(format(courtyard_y_edge, ".2f")) courtyard_x_lower_edge = float(format(courtyard_x_lower_edge, ".2f")) # drawing courtyard kicad_mod.append(Line(start=[courtyard_x, -courtyard_y], end=[courtyard_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_x, -courtyard_pad_y], end=[courtyard_pad_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_pad_x, -courtyard_pad_y], end=[courtyard_pad_x, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_pad_x, courtyard_pad_y], end=[courtyard_x, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[courtyard_x, courtyard_pad_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_edge, courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_edge, -courtyard_y], end=[courtyard_x, -courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) if fab_edge > 0: kicad_mod.append(Line(start=[-courtyard_x_lower_edge, courtyard_y_edge], end=[-courtyard_x_edge, courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_lower_edge, -courtyard_y_edge], end=[-courtyard_x_edge, -courtyard_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) if courtyard_y_edge > courtyard_pad_y: kicad_mod.append(Line(start=[-courtyard_x, -courtyard_y_edge], end=[-courtyard_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x, courtyard_pad_y], end=[-courtyard_x, courtyard_y_edge], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_x_lower_edge, -courtyard_pad_y], end=[-courtyard_pad_x, -courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_pad_x, -courtyard_pad_y], end=[-courtyard_pad_x, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Line(start=[-courtyard_pad_x, courtyard_pad_y], end=[-courtyard_x_lower_edge, courtyard_pad_y], layer='F.CrtYd', width=configuration['courtyard_line_width'])) lib_name ='Capacitor_SMD' # add model modelname = name.replace("_HandSoldering", "") kicad_mod.append(Model(filename="{model_prefix:s}{lib_name:s}.3dshapes/{name:s}.wrl".format(model_prefix=configuration['3d_model_prefix'], lib_name=lib_name, name=modelname), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # write file output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='Parse *.kicad_mod.yml file(s) and create matching footprints') parser.add_argument('files', metavar='file', type=str, nargs='+', help='yml-files to parse') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../SMD_chip_package_rlc-etc/config_KLCv3.0.yaml') parser.add_argument('--ipc_definition', type=str, nargs='?', help='the IPC definition file', default='ipc7351B_capae_crystal.yaml') parser.add_argument('--ipc_density', type=str, nargs='?', help='the IPC desnity', default='nominal') parser.add_argument('--force_rectangle_pads', action='store_true', help='Force the generation of rectangle pads instead of rounded rectangle (KiCad 4.x compatibility.)') #parser.add_argument('-v', '--verbose', help='show more information when creating footprint', action='store_true') # TODO: allow writing into sub file args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) ipc_doc = args.ipc_definition with open(ipc_doc, 'r') as ipc_stream: try: ipc_defintions = yaml.safe_load(ipc_stream) except yaml.YAMLError as exc: print(exc) configuration['ipc_density'] = args.ipc_density configuration['force_rectangle_pads'] = args.force_rectangle_pads for filepath in args.files: with open(filepath, 'r') as stream: try: yaml_parsed = yaml.safe_load(stream) for footprint in yaml_parsed: print("generate {name}.kicad_mod".format(name=footprint)) create_footprint(footprint, configuration , **yaml_parsed.get(footprint)) except yaml.YAMLError as exc: print(exc) ================================================ FILE: scripts/Capacitors_SMD/C_Elec_round.yaml ================================================ # http://nichicon-us.com/english/products/pdfs/e-uup.pdf # http://nichicon-us.com/english/products/pdfs/e-uwp.pdf # https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/ABA0000C1145.pdf # https://media.digikey.com/pdf/Data%20Sheets/Panasonic%20Electronic%20Components/S_Series_Type_V_.pdf # https://industrial.panasonic.com/cdbs/www-data/pdf/RDE0000/ABA0000C1157.pdf # Note: KLC puts pin 1 to the left so body_length is across the pins (horizontal) # Note: Due to minor variations in lead dimension for the same body size, # given dimensions are the greatest of all common body sizes in the datasheets # above. This may result in slightly more paste than if the lead size was # specific to one vendor's datasheet dimensions. However, as the lead sizes are # already large, lead-to-PCB coplanarity is quite varaible, and the capacitor # body does not sit flush with the PCB, the amount of paste is not extremely # critical. Pads a few tenths of a millimeter bigger or smaller than ideal # won't affect solderability or reliability. C_Elec_3x5.4: body_length: nominal: 3.3 tolerance: 0.2 body_width: nominal: 3.3 tolerance: 0.2 body_height: nominal: 5.4 body_diameter: nominal: 3.0 lead_width: minimum: 0.45 maximum: 0.65 lead_length: nominal: 1.5 tolerance: 0.2 lead_spacing: nominal: 0.6 pin1_chamfer: 'auto' C_Elec_4x5.4: body_length: nominal: 4.3 tolerance: 0.2 body_width: nominal: 4.3 tolerance: 0.2 body_height: nominal: 5.4 body_diameter: nominal: 4.0 lead_width: minimum: 0.5 maximum: 0.8 lead_length: nominal: 1.8 tolerance: 0.2 lead_spacing: nominal: 1.0 pin1_chamfer: 'auto' C_Elec_4x5.8: body_length: nominal: 4.3 tolerance: 0.2 body_width: nominal: 4.3 tolerance: 0.2 body_height: nominal: 5.8 body_diameter: nominal: 4.0 lead_width: minimum: 0.5 maximum: 0.8 lead_length: nominal: 1.8 tolerance: 0.2 lead_spacing: nominal: 1.0 pin1_chamfer: 'auto' C_Elec_5x5.4: body_length: nominal: 5.3 tolerance: 0.2 body_width: nominal: 5.3 tolerance: 0.2 body_height: nominal: 5.4 body_diameter: nominal: 5.0 lead_width: minimum: 0.5 maximum: 0.8 lead_length: minimum: 2.1 maximum: 2.2 lead_spacing: minimum: 1.3 maximum: 1.5 pin1_chamfer: 'auto' C_Elec_5x5.8: body_length: nominal: 5.3 tolerance: 0.2 body_width: nominal: 5.3 tolerance: 0.2 body_height: nominal: 5.8 body_diameter: nominal: 5.0 lead_width: minimum: 0.5 maximum: 0.8 lead_length: minimum: 2.1 maximum: 2.2 lead_spacing: minimum: 1.3 maximum: 1.5 pin1_chamfer: 'auto' C_Elec_6.3x5.4: body_length: nominal: 6.6 tolerance: 0.2 body_width: nominal: 6.6 tolerance: 0.2 body_height: nominal: 5.4 body_diameter: nominal: 6.3 lead_width: minimum: 0.5 maximum: 0.8 lead_length: minimum: 2.4 maximum: 2.6 lead_spacing: minimum: 1.8 maximum: 2.2 pin1_chamfer: 'auto' C_Elec_6.3x5.8: body_length: nominal: 6.6 tolerance: 0.2 body_width: nominal: 6.6 tolerance: 0.2 body_height: nominal: 5.8 body_diameter: nominal: 6.3 lead_width: minimum: 0.5 maximum: 0.8 lead_length: minimum: 2.4 maximum: 2.6 lead_spacing: minimum: 1.8 maximum: 2.2 pin1_chamfer: 'auto' C_Elec_6.3x7.7: body_length: nominal: 6.6 tolerance: 0.2 body_width: nominal: 6.6 tolerance: 0.2 body_height: nominal: 7.7 body_diameter: nominal: 6.3 lead_width: minimum: 0.5 maximum: 0.8 lead_length: minimum: 2.4 maximum: 2.6 lead_spacing: minimum: 1.8 maximum: 2.2 pin1_chamfer: 'auto' C_Elec_8x5.4: body_length: nominal: 8.3 tolerance: 0.2 body_width: nominal: 8.3 tolerance: 0.2 body_height: nominal: 5.4 body_diameter: nominal: 8.0 lead_width: minimum: 0.5 maximum: 0.8 lead_length: minimum: 3.3 maximum: 3.4 lead_spacing: minimum: 2.2 maximum: 2.3 pin1_chamfer: 'auto' C_Elec_8x6.2: body_length: nominal: 8.3 tolerance: 0.2 body_width: nominal: 8.3 tolerance: 0.2 body_height: nominal: 6.2 body_diameter: nominal: 8.0 lead_width: minimum: 0.5 maximum: 0.8 lead_length: minimum: 3.3 maximum: 3.4 lead_spacing: minimum: 2.2 maximum: 2.3 pin1_chamfer: 'auto' C_Elec_8x10.2: body_length: nominal: 8.3 tolerance: 0.2 body_width: nominal: 8.3 tolerance: 0.2 body_height: nominal: 10.2 body_diameter: nominal: 8.0 lead_width: minimum: 0.7 maximum: 1.1 lead_length: nominal: 3.4 tolerance: 0.2 lead_spacing: nominal: 3.1 pin1_chamfer: 'auto' C_Elec_10x10.2: body_length: nominal: 10.3 tolerance: 0.2 body_width: nominal: 10.3 tolerance: 0.2 body_height: nominal: 10.2 body_diameter: nominal: 10.0 lead_width: minimum: 0.7 maximum: 1.1 lead_length: nominal: 3.5 tolerance: 0.2 lead_spacing: nominal: 4.6 pin1_chamfer: 'auto' ================================================ FILE: scripts/Capacitors_SMD/C_Trimmer_config.yaml ================================================ # SMD trimmer capacitors STYLE A base: family: STYLE-A description: 'trimmer capacitor SMD horizontal' keywords: '' device: body: colour: 'white body' frame: colour: 'metal grey pins' contacts: colour: 'metal grey pins' cover: colour: 'white body' rotor: colour: 'white body' 3d_prefix: '${KISYS3DMOD}/Capacitors_SMD.3dshapes' variants: - series: TZR1 manufacturer: Murata footprint: x_mm: 2.2 pad: x_mm: 0.5 y_mm: 0.5 device: body: x_mm: 1.7 y_mm: 1.4 chamfer: sides: [] size_mm: 0.0 projection: sides: ['top', 'bottom', 'right'] offset_mm: 0.1 x_side_mm: 0.9 y_side_mm: 0.6 keywords: 'Murata TZR1' datasheet: http://www.murata.com/~/media/webrenewal/support/library/catalog/products/capacitor/trimmer/t13e.ashx?la=en-gb - series: TZY2 manufacturer: Murata footprint: x_mm: 4.0 pad: x_mm: 0.8 y_mm: 1.2 device: body: x_mm: 3.0 y_mm: 2.1 chamfer: sides: [] size_mm: 0.0 projection: sides: ['top', 'bottom', 'right'] offset_mm: 0.2 x_side_mm: 1.8 y_side_mm: 1.0 keywords: 'Murata TZY2' datasheet: http://www.murata.com/~/media/webrenewal/support/library/catalog/products/capacitor/trimmer/t13e.ashx?la=en-gb - series: TZW4 manufacturer: Murata footprint: x_mm: 7.0 pad: x_mm: 1.3 y_mm: 2.5 device: body: x_mm: 5.2 y_mm: 4.0 chamfer: sides: [] size_mm: 0.0 projection: sides: ['top', 'bottom'] offset_mm: 0.1 x_side_mm: 3.0 y_side_mm: 0.0 keywords: 'Murata TZW4' datasheet: http://www.murata.com/~/media/webrenewal/support/library/catalog/products/capacitor/trimmer/t13e.ashx?la=en-gb - series: JR manufacturer: Voltronics footprint: x_mm: 4.4 pad: x_mm: 1.0 y_mm: 1.8 device: body: x_mm: 3.5 y_mm: 3.1 chamfer: sides: ['left'] size_mm: 0.6 projection: sides: ['right'] offset_mm: 0.4 x_side_mm: 0.0 y_side_mm: 1.6 keywords: 'Voltronics JR' datasheet: http://www.knowlescapacitors.com/File%20Library/Voltronics/English/GlobalNavigation/Products/Trimmer%20Capacitors/CerChipTrimCap.pdf - series: JN manufacturer: Voltronics footprint: x_mm: 2.2 pad: x_mm: 0.5 y_mm: 0.5 device: body: x_mm: 1.7 y_mm: 1.4 chamfer: sides: [] size_mm: 0.0 projection: sides: ['top', 'bottom', 'right'] offset_mm: 0.1 x_side_mm: 0.9 y_side_mm: 0.6 keywords: 'Voltronics JN' datasheet: http://www.knowlescapacitors.com/File%20Library/Voltronics/English/GlobalNavigation/Products/Trimmer%20Capacitors/CerChipTrimCap.pdf - series: JV manufacturer: Voltronics footprint: x_mm: 4.0 pad: x_mm: 0.8 y_mm: 1.2 device: body: x_mm: 3.0 y_mm: 2.1 chamfer: sides: [] size_mm: 0.0 projection: sides: ['top', 'bottom', 'right'] offset_mm: 0.2 x_side_mm: 1.8 y_side_mm: 1.0 keywords: 'Voltronics JV' datasheet: http://www.knowlescapacitors.com/File%20Library/Voltronics/English/GlobalNavigation/Products/Trimmer%20Capacitors/CerChipTrimCap.pdf - series: JQ manufacturer: Voltronics footprint: x_mm: 3.2 pad: x_mm: 0.55 y_mm: 1.0 device: body: x_mm: 2.5 y_mm: 1.8 chamfer: sides: [] size_mm: 0.0 projection: sides: ['top', 'bottom', 'right'] offset_mm: 0.2 x_side_mm: 1.5 y_side_mm: 1.0 keywords: 'Voltronics JQ' datasheet: http://www.knowlescapacitors.com/File%20Library/Voltronics/English/GlobalNavigation/Products/Trimmer%20Capacitors/CerChipTrimCap.pdf --- # SMD trimmer capacitors STYLE B base: family: STYLE-B description: 'trimmer capacitor SMD horizontal' keywords: '' device: body: colour: 'white body' frame: colour: 'metal grey pins' contacts: colour: 'metal grey pins' cover: colour: 'white body' rotor: colour: 'white body' 3d_prefix: '${KISYS3DMOD}/Capacitors_SMD.3dshapes' variants: - series: TZC3 manufacturer: Murata footprint: x_mm: 5.0 pad: x_mm: 0.85 y_mm: 1.0 device: body: x_mm: 4.5 y_mm: 3.2 chamfer: sides: ['left'] size_mm: 0.6 projection: sides: [] offset_mm: x_side_mm: y_side_mm: keywords: 'Murata TZC3' datasheet: http://www.murata.com/~/media/webrenewal/support/library/catalog/products/capacitor/trimmer/t13e.ashx?la=en-gb --- # SMD trimmer capacitors STYLE C base: family: STYLE-C description: 'trimmer capacitor SMD horizontal' keywords: '' device: body: colour: 'white body' frame: colour: 'metal grey pins' contacts: colour: 'metal grey pins' cover: colour: 'white body' rotor: colour: 'white body' 3d_prefix: '${KISYS3DMOD}/Capacitors_SMD.3dshapes' variants: - series: JZ manufacturer: Voltronics footprint: x_mm: 4.8 pad: x_mm: 0.9 y_mm: 1.4 device: body: x_mm: 4.5 y_mm: 3.2 chamfer: sides: ['left'] size_mm: 0.6 projection: sides: [] offset_mm: x_side_mm: y_side_mm: keywords: 'Voltronics JR' datasheet: http://www.knowlescapacitors.com/File%20Library/Voltronics/English/GlobalNavigation/Products/Trimmer%20Capacitors/CerChipTrimCap.pdf - series: SGC3 manufacturer: Sprague-Goodman footprint: x_mm: 4.75 pad: x_mm: 1.075 y_mm: 1.4 device: body: x_mm: 4.5 y_mm: 3.2 chamfer: sides: ['left'] size_mm: 0.6 projection: sides: [] offset_mm: x_side_mm: y_side_mm: keywords: 'Sprague Goodman SGC3' datasheet: http://media.wix.com/ugd/d86717_38d9821e12823a7aa9cef38c6c2a73cc.pdf --- # SMD trimmer capacitors STYLE D base: family: STYLE-D description: 'trimmer capacitor SMD horizontal' keywords: '' device: body: colour: 'white body' frame: colour: 'metal grey pins' contacts: colour: 'metal grey pins' cover: colour: 'white body' rotor: colour: 'white body' 3d_prefix: '${KISYS3DMOD}/Capacitors_SMD.3dshapes' variants: - series: TZB4-A manufacturer: Murata footprint: x_mm: 7.0 pad: x_mm: 2.3 y_mm: 1.6 device: body: x_mm: 4.5 y_mm: 4.0 chamfer: sides: [] size_mm: projection: sides: ['left', 'right'] offset_mm: 0.25 x_side_mm: y_side_mm: 1.2 keywords: 'Murata TZB4 TZB4-A' datasheet: http://www.murata.com/~/media/webrenewal/support/library/catalog/products/capacitor/trimmer/t13e.ashx?la=en-gb - series: TZB4-B manufacturer: Murata footprint: x_mm: 8.0 pad: x_mm: 2.0 y_mm: 1.6 device: body: x_mm: 4.5 y_mm: 4.0 chamfer: sides: [] size_mm: projection: sides: ['left', 'right'] offset_mm: 1.25 x_side_mm: y_side_mm: 1.2 keywords: 'Murata TZB4 TZB4-A' datasheet: http://www.murata.com/~/media/webrenewal/support/library/catalog/products/capacitor/trimmer/t13e.ashx?la=en-gb --- ================================================ FILE: scripts/Capacitors_SMD/C_Trimmer_factory.py ================================================ import sys import os import argparse import yaml import pprint sys.path.append(os.path.join(sys.path[0], "../..")) # enable package import from parent directory from KicadModTree import * # NOQA from bump import * from corners import * from chamfers import * class Dimensions(object): def __init__(self, base, variant, cut_pin=False, tab_linked=False): footprint = variant['footprint'] device = variant['device'] # FROM KLC self.fab_line_width_mm = 0.1 self.fab_text_size = [1.0, 1.0] self.fab_text_thickness = 0.15 self.fab_reference_text_size = [0.5, 0.5] self.fab_reference_text_thickness = 0.05 self.silk_line_width_mm = 0.12 self.silk_text_size = [1.0, 1.0] self.silk_text_thickness = 0.15 self.courtyard_line_width_mm = 0.05 self.courtyard_clearance_mm = 0.25 self.courtyard_precision_mm = 0.01 # NAME self.name = self._footprint_name(variant['manufacturer'], variant['series']) # PADS self.pad_offset_x_mm = (footprint['pad']['x_mm'] - footprint['x_mm']) / 2.0 # FAB OUTLINE self.device_offset_x_mm = device['body']['x_mm'] / 2.0 # x coordinate of RHS of device self.body_x_mm = device['body']['x_mm'] self.body_offset_y_mm = device['body']['y_mm'] / 2.0 # y coordinate of bottom of body # COURTYARD self.biggest_x_mm = footprint['x_mm'] self.biggest_y_mm = device['body']['y_mm'] if 'top' in device['projection']['sides'] or 'bottom' in device['projection']['sides']: self.biggest_y_mm += 2.0 * device['projection']['offset_mm'] self.courtyard_offset_x_mm = self._round_to(self.courtyard_clearance_mm + self.biggest_x_mm / 2.0, self.courtyard_precision_mm) self.courtyard_offset_y_mm = self._round_to(self.courtyard_clearance_mm + self.biggest_y_mm / 2.0, self.courtyard_precision_mm) # SILKSCREEN self.label_centre_x_mm = 0 self.label_centre_y_mm = self.courtyard_offset_y_mm + 1 self.silk_offset_mm = (0.2, 0.2) # amount to shift silkscreen in X and Y directions to avoid overlapping fab lines def _round_to(self, n, precision): correction = 0.5 if n >= 0 else -0.5 return int(n / precision + correction) * precision def _footprint_name(self, manufacturer, series): name = 'C_Trimmer_{m:s}_{s:s}'.format(m=manufacturer, s=series) return name class CapacitorTrimmer(object): def __init__(self, config_file): self.FAMILY = None self.config = None def _load_config(self, config_file): try: devices = yaml.safe_load_all(open(config_file)) except FileNotFoundError as fnfe: print(fnfe) return config = None for dev in devices: if dev['base']['family'] == self.FAMILY: config = dev break return config def _add_properties(self, m, variant): m.setDescription('{bd:s}, {vd:s}'.format(bd=self.config['base']['description'], vd=variant['datasheet'])) m.setTags('{bk:s} {vk:s}'.format(bk=self.config['base']['keywords'], vk=variant['keywords'])) m.setAttribute('smd') return m def _add_labels(self, m, variant, dim): m.append(Text(type='reference', text='REF**', size=dim.silk_text_size, thickness=dim.silk_text_thickness, at=[dim.label_centre_x_mm, -dim.label_centre_y_mm], layer='F.SilkS')) m.append(Text(type='user', text='%R', size=dim.fab_reference_text_size, thickness=dim.fab_reference_text_thickness, at=[0, 0], layer='F.Fab')) m.append(Text(type='value', text=dim.name, size=dim.fab_text_size, thickness=dim.fab_text_thickness, at=[dim.label_centre_x_mm, dim.label_centre_y_mm], layer='F.Fab')) return m def _draw_pads(self, m, variant, dim): m.append(Pad(number=1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[dim.pad_offset_x_mm, 0], size=[variant['footprint']['pad']['x_mm'], variant['footprint']['pad']['y_mm']], layers=Pad.LAYERS_SMT)) m.append(Pad(number=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[-dim.pad_offset_x_mm, 0], size=[variant['footprint']['pad']['x_mm'], variant['footprint']['pad']['y_mm']], layers=Pad.LAYERS_SMT)) return m def _draw_fab_outline(self, m, variant, dim, width, offset): # draw body right_x = dim.device_offset_x_mm left_x = right_x - dim.body_x_mm top_y = -dim.body_offset_y_mm bottom_y = -top_y if 'left' in variant['device']['chamfer']['sides']: chamfers = [{'corner': 'topleft', 'size': variant['device']['chamfer']['size_mm']}, {'corner': 'bottomleft', 'size': variant['device']['chamfer']['size_mm']}] elif 'right' in variant['device']['chamfer']['sides']: chamfers = [{'corner': 'topright', 'size': variant['device']['chamfer']['size_mm']}, {'corner': 'bottomright', 'size': variant['device']['chamfer']['size_mm']}] else: chamfers = [] m = add_rect_chamfer(m, [left_x, top_y], [right_x, bottom_y], 'F.Fab', width, offset, chamfers) m.append(Circle(center=[0, 0], radius=dim.body_offset_y_mm, layer='F.Fab', width=width)) # add frame extensions p = variant['device']['projection'] if 'top' in p['sides']: m = add_bump(m, [0, top_y], p['x_side_mm'], p['offset_mm'], 'up', 'F.Fab', width, offset) if 'bottom' in p['sides']: m = add_bump(m, [0, bottom_y], p['x_side_mm'], p['offset_mm'], 'down', 'F.Fab', width, offset) if 'right' in p['sides']: m = add_bump(m, [right_x, 0], p['y_side_mm'], p['offset_mm'], 'right', 'F.Fab', width, offset) if 'left' in p['sides']: m = add_bump(m, [left_x, 0], p['y_side_mm'], p['offset_mm'], 'left', 'F.Fab', width, offset) return m def _draw_silk_outline(self, m, variant, dim, width, offset): right_x = dim.device_offset_x_mm left_x = right_x - dim.body_x_mm top_y = -dim.body_offset_y_mm bottom_y = -top_y if 'left' in variant['device']['chamfer']['sides']: chamfers = ['topleft', 'bottomleft'] elif 'right' in variant['device']['chamfer']['sides']: chamfers = ['topright', 'bottomright'] else: chamfers = [] m = add_corners(m, [left_x, top_y], [right_x, bottom_y], 0.5, 0.5, 'F.SilkS', width, offset, chamfers) return m def _draw_courtyard(self, m ,dim): m.append(RectLine(start=[-dim.courtyard_offset_x_mm, -dim.courtyard_offset_y_mm], end=[dim.courtyard_offset_x_mm, dim.courtyard_offset_y_mm], layer='F.CrtYd', width=dim.courtyard_line_width_mm)) return m def _add_3D_model(self, m, base, dim): m.append( Model(filename="{p:s}/{n:s}.wrl".format(p=base['3d_prefix'], n=dim.name), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) return m def _build_footprint(self, base, variant, cut_pin=False, tab_linked=False, verbose=False): # calculate dimensions and other attributes specific to this variant dim = Dimensions(base, variant, cut_pin, tab_linked) # initialise footprint kicad_mod = Footprint(dim.name) kicad_mod = self._add_properties(kicad_mod, variant) kicad_mod = self._add_labels(kicad_mod, variant, dim) # create pads kicad_mod = self._draw_pads(kicad_mod, variant, dim) # create fab outline kicad_mod = self._draw_fab_outline(kicad_mod, variant, dim, dim.fab_line_width_mm, (0, 0)) # create silkscreen outline kicad_mod = self._draw_silk_outline(kicad_mod, variant, dim, dim.silk_line_width_mm, dim.silk_offset_mm) # create courtyard kicad_mod = self._draw_courtyard(kicad_mod, dim) # add 3D model kicad_mod = self._add_3D_model(kicad_mod, base, dim) # print render tree if verbose: print('\r\nMaking {n:s}'.format(n=dim.name)) print(kicad_mod.getRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{:s}.kicad_mod'.format(dim.name)) def build_series(self, verbose=False): print('Making {p:s}'.format(p=self.config['base']['description'])) base = self.config['base'] for variant in self.config['variants']: self._build_footprint(base, variant, verbose=verbose) class StyleA(CapacitorTrimmer): def __init__(self, config_file): self.FAMILY = 'STYLE-A' self.config = self._load_config(config_file) class StyleB(CapacitorTrimmer): def __init__(self, config_file): self.FAMILY = 'STYLE-B' self.config = self._load_config(config_file) class StyleC(CapacitorTrimmer): def __init__(self, config_file): self.FAMILY = 'STYLE-C' self.config = self._load_config(config_file) class StyleD(CapacitorTrimmer): def __init__(self, config_file): self.FAMILY = 'STYLE-D' self.config = self._load_config(config_file) class Factory(object): def __init__(self, config_file): self._config_file = config_file self._parse_command_line() self.verbose = self._args.verbose self._create_build_list() def _parse_command_line(self): parser = argparse.ArgumentParser(description='Select which devices to make') parser.add_argument('--family', help='device families to make: STYLE-A | STYLE-B | STYLE-C | STYLE-D (default is all families)', type=str, nargs=1) parser.add_argument('-v', '--verbose', help='show detailed information while making the footprints', action='store_true') self._args = parser.parse_args() def _create_build_list(self): if not self._args.family: self.build_list = [StyleA(self._config_file), StyleB(self._config_file), StyleC(self._config_file), StyleD(self._config_file)] else: self.build_list = [] if 'STYLE-A' in self._args.family: self.build_list.append(StyleA(self._config_file)) if 'STYLE-B' in self._args.family: self.build_list.append(StyleB(self._config_file)) if 'STYLE-C' in self._args.family: self.build_list.append(StyleC(self._config_file)) if 'STYLE-D' in self._args.family: self.build_list.append(StyleD(self._config_file)) if not self.build_list: print('Family not recognised') ================================================ FILE: scripts/Capacitors_SMD/C_Trimmer_make.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os import argparse import yaml import pprint sys.path.append(os.path.join(sys.path[0], "../..")) # enable package import from parent directory from KicadModTree import * # NOQA if __name__ == '__main__': print('Making DPAK footprints') from C_Trimmer_factory import * CONFIG = 'C_Trimmer_config.yaml' f = Factory(CONFIG) for series in f.build_list: series.build_series(verbose=f.verbose) ================================================ FILE: scripts/Capacitors_SMD/bump.py ================================================ from KicadModTree import * # NOQA def add_bump(m, anchor_pos, bump_length, bump_width, direction, layer, width, offset=(0, 0)): if direction == 'up': delta_x = bump_length delta_y = -bump_width start_x = anchor_pos[0] start_y = anchor_pos[1] - offset[1] elif direction == 'down': delta_x = bump_length delta_y = bump_width start_x = anchor_pos[0] start_y = anchor_pos[1] + offset[1] elif direction == 'left': delta_x = -bump_width delta_y = bump_length start_x = anchor_pos[0] - offset[0] start_y = anchor_pos[1] elif direction == 'right': delta_x = bump_width delta_y = bump_length start_x = anchor_pos[0] + offset[0] start_y = anchor_pos[1] else: return m if direction in ['up', 'down']: polygon_line = [ {'x': start_x - delta_x / 2.0, 'y': start_y }, {'x': start_x - delta_x / 2.0, 'y': start_y + delta_y}, {'x': start_x + delta_x / 2.0, 'y': start_y + delta_y}, {'x': start_x + delta_x / 2.0, 'y': start_y} ] else: polygon_line = [ {'x': start_x, 'y': start_y - delta_y / 2.0 }, {'x': start_x + delta_x, 'y': start_y - delta_y / 2.0}, {'x': start_x + delta_x, 'y': start_y + delta_y / 2.0}, {'x': start_x, 'y': start_y + delta_y / 2.0} ] m.append(PolygoneLine(polygone=polygon_line, layer=layer, width=width)) return m ================================================ FILE: scripts/Capacitors_SMD/chamfers.py ================================================ from KicadModTree import * def add_rect_chamfer(m, start_pos, end_pos, layer, width, offset=(0,0), chamfers=[]): # For the offset and chamfer to work properly, start-pos must be top-left, and end-pos must be bottom-right x1 = min(start_pos[0], end_pos[0]) x2 = max(start_pos[0], end_pos[0]) y1 = min(start_pos[1], end_pos[1]) y2 = max(start_pos[1], end_pos[1]) # Put the offset (if any) back in start_pos[0] = x1 - offset[0] start_pos[1] = y1 - offset[1] end_pos[0] = x2 + offset[0] end_pos[1] = y2 + offset[1] # Work out intermediate positions on each side to use later when drawing corners or chamfers JOG = 0.01 # avoid coincident intermediate points on non-chamfered sides top_left_mid_pos = Point([start_pos[0] + JOG, start_pos[1]]) top_right_mid_pos = Point([end_pos[0] - JOG, start_pos[1]]) bottom_left_mid_pos = Point([start_pos[0] + JOG, end_pos[1]]) bottom_right_mid_pos = Point([end_pos[0] - JOG, end_pos[1]]) left_top_mid_pos = Point([start_pos[0], start_pos[1] + JOG]) left_bottom_mid_pos = Point([start_pos[0], end_pos[1] - JOG]) right_top_mid_pos = Point([end_pos[0], start_pos[1] + JOG]) right_bottom_mid_pos = Point([end_pos[0], end_pos[1] - JOG]) # Set the positions of the corners top_left_pos = Point([start_pos[0], start_pos[1]]) top_right_pos = Point([end_pos[0], start_pos[1]]) bottom_left_pos = Point([start_pos[0], end_pos[1]]) bottom_right_pos = Point([end_pos[0], end_pos[1]]) for c in chamfers: # Need to shift chamfered edges so they maintain constant distance from non-offset line # tan(22.5) = 0.414 works correctly when chamfer is at 45 degrees (same and Y offset), # and still looks OK when X and Y offsets are different try: x_delta = c['size'] + 0.414 * offset[0] y_delta = c['size'] + 0.414 * offset[1] if c['corner'] == 'topleft': top_left_pos.x = start_pos[0] + (x_delta) / 2.0 top_left_pos.y = start_pos[1] + (y_delta) / 2.0 top_left_mid_pos.x = start_pos[0] + (x_delta) left_top_mid_pos.y = start_pos[1] + (y_delta) elif c['corner'] == 'topright': top_right_pos.x = end_pos[0] - (x_delta) / 2.0 top_right_pos.y = start_pos[1] + (y_delta) / 2.0 top_right_mid_pos.x = end_pos[0] - (x_delta) right_top_mid_pos.y = start_pos[1] + (y_delta) elif c['corner'] == 'bottomleft': bottom_left_pos.x = start_pos[0] + (x_delta) / 2.0 bottom_left_pos.y = end_pos[1] - (y_delta) / 2.0 bottom_left_mid_pos.x = start_pos[0] + (x_delta) left_bottom_mid_pos.y = end_pos[1] - (y_delta) elif c['corner'] == 'bottomright': bottom_right_pos.x = end_pos[0] - (x_delta) / 2.0 bottom_right_pos.y = end_pos[1] - (y_delta) / 2.0 bottom_right_mid_pos.x = end_pos[0] - (x_delta) right_bottom_mid_pos.y = end_pos[1] - (y_delta) elif c['corner'] == 'all': chamfers.append({'corner': 'topleft', 'size': c['size']}) chamfers.append({'corner': 'topright', 'size': c['size']}) chamfers.append({'corner': 'bottomleft', 'size': c['size']}) chamfers.append({'corner': 'bottomright', 'size': c['size']}) else: pass except Exception as e: # print(e) pass polygon_line = [ {'x': top_left_pos.x, 'y': top_left_pos.y}, {'x': top_left_mid_pos.x, 'y': top_left_mid_pos.y}, {'x': top_right_mid_pos.x, 'y': top_right_mid_pos.y}, {'x': top_right_pos.x, 'y': top_right_pos.y}, {'x': right_top_mid_pos.x, 'y': right_top_mid_pos.y}, {'x': right_bottom_mid_pos.x, 'y': right_bottom_mid_pos.y}, {'x': bottom_right_pos.x, 'y': bottom_right_pos.y}, {'x': bottom_right_mid_pos.x, 'y': bottom_right_mid_pos.y}, {'x': bottom_left_mid_pos.x, 'y': bottom_left_mid_pos.y}, {'x': bottom_left_pos.x, 'y': bottom_left_pos.y}, {'x': left_bottom_mid_pos.x, 'y': left_bottom_mid_pos.y}, {'x': left_top_mid_pos.x, 'y': left_top_mid_pos.y}, {'x': top_left_pos.x, 'y': top_left_pos.y} ] m.append(PolygoneLine(polygone=polygon_line, layer=layer, width=width)) return m ================================================ FILE: scripts/Capacitors_SMD/corners.py ================================================ from KicadModTree import * # NOQA def add_corners(m, start_pos, end_pos, size_x, size_y, layer, width, offset=(0, 0), chamfers=[]): # If specifed, an 'offset' can be applied to the corners. # For example, creating corners around a given Rect of a specified size # offset for the rect line # For the offset to work properly, start-pos must be top-left, and end-pos must be bottom-right x1 = min(start_pos[0], end_pos[0]) x2 = max(start_pos[0], end_pos[0]) y1 = min(start_pos[1], end_pos[1]) y2 = max(start_pos[1], end_pos[1]) # Put the offset (if any) back in start_pos[0] = x1 - offset[0] start_pos[1] = y1 - offset[1] end_pos[0] = x2 + offset[0] end_pos[1] = y2 + offset[1] if 'topleft' in chamfers: m.append(Line(start=[start_pos[0], start_pos[1] + size_y], end=[start_pos[0] + size_x, start_pos[1]], layer=layer, width=width)) else: m.append(Line(start=[start_pos[0], start_pos[1]], end=[start_pos[0] + size_x, start_pos[1]], layer=layer, width=width)) m.append(Line(start=[start_pos[0], start_pos[1]], end=[start_pos[0], start_pos[1] + size_y], layer=layer, width=width)) if 'bottomleft' in chamfers: m.append(Line(start=[start_pos[0], end_pos[1] - size_y], end=[start_pos[0] + size_x, end_pos[1]], layer=layer, width=width)) else: m.append(Line(start=[start_pos[0], end_pos[1]], end=[start_pos[0] + size_x, end_pos[1]], layer=layer, width=width)) m.append(Line(start=[start_pos[0], end_pos[1]], end=[start_pos[0], end_pos[1] - size_y], layer=layer, width=width)) if 'topright' in chamfers: m.append(Line(start=[end_pos[0], start_pos[1] + size_y], end=[end_pos[0] - size_x, start_pos[1]], layer=layer, width=width)) else: m.append(Line(start=[end_pos[0], start_pos[1]], end=[end_pos[0] - size_x, start_pos[1]], layer=layer, width=width)) m.append(Line(start=[end_pos[0], start_pos[1]], end=[end_pos[0], start_pos[1] + size_y], layer=layer, width=width)) if 'bottomright' in chamfers: m.append(Line(start=[end_pos[0], end_pos[1] - size_y], end=[end_pos[0] - size_x, end_pos[1]], layer=layer, width=width)) else: m.append(Line(start=[end_pos[0], end_pos[1]], end=[end_pos[0] - size_x, end_pos[1]], layer=layer, width=width)) m.append(Line(start=[end_pos[0], end_pos[1]], end=[end_pos[0], end_pos[1] - size_y], layer=layer, width=width)) return m ================================================ FILE: scripts/Capacitors_SMD/ipc7351B_capae_crystal.yaml ================================================ # Dimensions taken from ipc7351b table 3-20 # Aluminum Electrolytic Capacitor and 2-Pin Crystal # | Minimum | Median | Maximum | # | (Most) | (Nominal) | (Least) | # | Density | Density | Density | round # Lead Part | Level A | Level B | Level C | to # ----------+---------+-----------+---------+- # Toe (JT) | 0.7 | 0.5 | 0.3 | 0.05 # >=10mm | 1.0 | 0.7 | 0.4 # Heel (JH) | 0.0 | -0.1 | -0.2 | 0.05 # >=10mm | 0.0 | -0.05 | -0.1 # Side (JS) | 0.5 | 0.4 | 0.03 | 0.05 # >=10mm | 0.6 | 0.5 | 0.4 # Courtyard | 1.0 | 0.5 | 0.25 | ipc_spec_capae_crystal: most: toe: 0.7 heel: 0 side: 0.5 courtyard: 1.0 most_10mm: toe: 1.0 heel: 0.0 side: 0.6 courtyard: 1.0 nominal: toe: 0.5 heel: -0.1 side: 0.4 courtyard: 0.5 nominal_10mm: toe: 0.7 heel: -0.05 side: 0.5 courtyard: 0.5 least: toe: 0.3 heel: -0.2 side: 0.03 courtyard: 0.25 least_10mm: toe: 0.4 heel: -0.1 side: 0.4 courtyard: 0.25 round_base: toe: 0.05 heel: 0.05 side: 0.05 ================================================ FILE: scripts/Capacitors_SMD/tantal and normal smd generator found under SMD_chip_package_rlc-etc ================================================ ================================================ FILE: scripts/Capacitors_THT/make_Capacitors_THT.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_resistorlike import * if __name__ == '__main__': R_POW = 0 specialtags=["Capacitor"] ########################################################### # rectangular capacitors ########################################################### type = "simple" # w d h rm ddrill name_additions add_description caps=[ [ 13, 3, 10, 10, 1, ["FKS3","FKP3","MKS4"], "http://www.wima.com/EN/WIMA_FKS_3.pdf, http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 13, 4, 10, 10, 1, ["FKS3","FKP3","MKS4"], "http://www.wima.com/EN/WIMA_FKS_3.pdf, http://www.wima.com/EN/WIMA_MKS_4.pdf"], [13.5, 4, 10, 10, 1, ["FKS3","FKP3","MKS4"], "http://www.wima.com/EN/WIMA_FKS_3.pdf, http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 13, 5, 10, 10, 1, ["FKS3","FKP3","MKS4"], "http://www.wima.com/EN/WIMA_FKS_3.pdf, http://www.wima.com/EN/WIMA_MKS_4.pdf"], [13.5, 5, 10, 10, 1, ["FKS3","FKP3","MKS4"], "http://www.wima.com/EN/WIMA_FKS_3.pdf, http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 13, 6, 10, 10, 1, ["FKS3","FKP3","MKS4"], "http://www.wima.com/EN/WIMA_FKS_3.pdf, http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 13, 8, 10, 10, 1, ["FKS3","FKP3","MKS4"], "http://www.wima.com/EN/WIMA_FKS_3.pdf, http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 10, 3, 8.5, 7.5, 1, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 10, 4, 8.5, 7.5, 1, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 18, 5, 15, 15, 1.2, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 18, 6, 15, 15, 1.2, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 18, 7, 15, 15, 1.2, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 18, 8, 15, 15, 1.2, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 18, 9, 15, 15, 1.2, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 18, 11, 15, 15, 1.2, ["FKS3","FKP3"], "http://www.wima.com/EN/WIMA_FKS_3.pdf"], [ 19, 5, 15, 15, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 19, 6, 15, 15, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 19, 7, 15, 15, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 19, 8, 15, 15, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 19, 9, 15, 15, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 19, 11, 15, 15, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [26.5, 5, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [26.5, 6, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [26.5, 7, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [26.5, 8.5, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [26.5,10.5, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [26.5,11.5, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 28, 8, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 28, 10, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 28, 12, 21, 22.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [31.5, 9, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [31.5, 11, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [31.5, 13, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [31.5, 15, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [31.5, 17, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [31.5, 20, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 33, 13, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 33, 15, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 33, 20, 26, 27.5, 1.2, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 9, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 11, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 13, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 15, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 17, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 19, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 20, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 24, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 31, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 35, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [41.5, 40, 44, 37.5, 1.4, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 56, 19, 48.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 56, 23, 48.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 56, 27, 48.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 56, 33, 48.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 56, 37, 48.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 57, 25, 52.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 57, 45, 52.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 57, 50, 52.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 57, 55, 52.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], #[ 57, 65, 52.5, 1.1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 27, 9, 21, 22, 1.1, [""], ""], [ 27, 9, 21, 23, 1.1, [""], ""], [ 27, 11, 21, 22, 1.1, [""], ""], [ 32, 15, 26, 27, 1.1, [""], ""], [ 4, 2.5, 10, 2.5, 0.8, [""], ""], [ 7.5, 6.5, 10, 5, 0.8, [""], ""], [ 7, 2.5, 10, 5, 0.8, [""], ""], [ 7, 2, 10, 5, 0.8, [""], ""], [ 7, 2.5, 10, 5, 0.8, [""], ""], [ 7, 3.5, 10, 5, 0.8, [""], ""], [ 7, 4.5, 10, 5, 0.8, [""], ""], [ 7, 6, 10, 5, 0.8, [""], ""], [ 7, 6.5, 10, 5, 0.9, [""], ""], [ 4.6, 5.5, 7, 2.5, 0.7, ["MKS02", "FKP02"], "http://www.wima.de/DE/WIMA_MKS_02.pdf"], [ 4.6, 4.6, 7, 2.5, 0.7, ["MKS02", "FKP02"], "http://www.wima.de/DE/WIMA_MKS_02.pdf"], [ 4.6, 3.8, 7, 2.5, 0.7, ["MKS02", "FKP02"], "http://www.wima.de/DE/WIMA_MKS_02.pdf"], [ 4.6, 3.0, 7, 2.5, 0.7, ["MKS02", "FKP02"], "http://www.wima.de/DE/WIMA_MKS_02.pdf"], [ 4.6, 2, 7, 2.5, 0.7, ["MKS02", "FKP02"], "http://www.wima.de/DE/WIMA_MKS_02.pdf"], [ 7.2, 2.5, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 3.0, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 3.5, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 4.5, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 5.5, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 7.2, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 8.5, 9, 5, 0.8, ["FKP2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 11, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 7.2, 2.5, 9, 5, 0.8, ["FKS2","FKP2","MKS2","MKP2"], "http://www.wima.com/EN/WIMA_FKS_2.pdf"], [ 10, 2.5, 9, 7.5, 1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 10, 3.0, 9, 7.5, 1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [ 10, 4.0, 9, 7.5, 1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [10.3, 4.5, 9, 7.5, 1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [10.3, 5, 9, 7.5, 1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [10.3, 5.7, 9, 7.5, 1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], [10.3, 7.2, 9, 7.5, 1, ["MKS4"], "http://www.wima.com/EN/WIMA_MKS_4.pdf"], ] for w in [2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.6, 3.8, 3.9, 4.0, 4.2, 4.9, 5.1, 5.7, 6.4, 6.7, 7.7, 8.5, 9.5, 9.8]: caps+=[ 9, w, 8, 7.5, 0.8, ["MKT"], "https://en.tdk.eu/inf/20/20/db/fc_2009/MKT_B32560_564.pdf"], for w in [2.8,3.4,3.5,4.2,4.3,5.1,5.3,6.3,6.4,7.3,8.8]: caps+=[11.0, w, 10, 10, 0.8, ["MKT"], "https://en.tdk.eu/inf/20/20/db/fc_2009/MKT_B32560_564.pdf"], for w in [2,5,2.6,2.8,3.2,3.5,3.6,4.0,4.3,4.5,5.1,5.2,5.6,6.4,6.6,6.9,7.3,7.5,7.8,8.0,8.8,9.5,9.8]: caps+=[11.5, w, 10, 10, 0.8, ["MKT"], "https://en.tdk.eu/inf/20/20/db/fc_2009/MKT_B32560_564.pdf"], for w in [4.7,4.9,5,6,7,7.3,8.7,8.9,9,9.2,10.7,10.9,11.2,11.8,13.5,13.7,13.9]: caps+=[16.5, w, 14, 15, 1.1, ["MKT"], "https://en.tdk.eu/inf/20/20/db/fc_2009/MKT_B32560_564.pdf"], for w in [7,8.3,8.6,10.1,10.3,10.9,12.2,12.6,12.8]: caps+=[ 24, w, 15, 22.5, 1.2, ["MKT"], "https://en.tdk.eu/inf/20/20/db/fc_2009/MKT_B32560_564.pdf"], for w in [7.6,7.8,7.9,9.1,9.6,11,11.9,12.2,13,13.8,14.2,16]: caps+=[ 29, w, 19, 27.5, 1.2, ["MKT"], "https://en.tdk.eu/inf/20/20/db/fc_2009/MKT_B32560_564.pdf"], script3rect="CQ_params_C_Rect.py" with open(script3rect, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") for c in caps: seriesname = "Rect"; w = c[0]; d = c[1]; h3d=c[2] w2 = 0; rm = c[3]; ddrill = c[4]; add_description = c[6]; name_additions = c[5] scr=script3rect makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=d, ddrill=ddrill, R_POW=R_POW, type=type, w2=w2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=specialtags, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT_Rectangular", script3d=scr, height3d=h3d) ########################################################### # rectangular capacitors with 2 RMs ########################################################### caps=[] # w h rm rm2 ddrill caps+=[ 7, 3.5, 2.5, 5, 0.8, [""], ""], caps+=[ 10, 5, 5, 7.5, 0.8, [""], ""], caps+=[ 13, 6.5, 7.5, 10, 0.8, [""], ""], for c in caps: seriesname = "Rect"; type="simple" w = c[0]; d = c[1]; w2 = 0; rm = c[2]; rm2 = c[3]; ddrill = c[4]; add_description = c[6]; name_additions = c[5] scr = script3rect makeResistorRadial(seriesname=seriesname, rm=rm, rm2=rm2, w=w, h=d, ddrill=ddrill, R_POW=R_POW, type=type, w2=w2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=specialtags, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT_Rectangular", script3d=scr, height3d=10) ########################################################### # disc capacitors ########################################################### # d w rm ddrill name_additions add_description caps = [ [ 12, 4.4, 7.75, 1.2, [], ""], [ 3, 2, 2.5, 0.8, [], ""], [ 6, 4.4, 5, 0.8, [], ""], [ 7.5, 4.4, 5, 0.8, [], ""], [ 5, 2.5, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/DS_KERKO_TC.pdf"], [ 5, 2.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/DS_KERKO_TC.pdf"], [ 6, 2.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/DS_KERKO_TC.pdf"], [ 7, 2.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/DS_KERKO_TC.pdf"], [ 8, 2.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/DS_KERKO_TC.pdf"], [ 9, 2.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/DS_KERKO_TC.pdf"], [ 10, 2.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/DS_KERKO_TC.pdf"], [ 3.0,1.6, 2.5, 0.8, [], "http://www.vishay.com/docs/45233/krseries.pdf"], [ 3.4,2.1, 2.5, 0.8, [], "http://www.vishay.com/docs/45233/krseries.pdf"], [ 3.8,2.6, 2.5, 0.8, [], "http://www.vishay.com/docs/45233/krseries.pdf"], [ 4.3,1.9, 5, 0.8, [], "http://www.vishay.com/docs/45233/krseries.pdf"], [ 4.7,2.5, 5, 0.8, [], "http://www.vishay.com/docs/45233/krseries.pdf"], [ 5.1,3.2, 5, 0.8, [], "http://www.vishay.com/docs/45233/krseries.pdf"], [ 7.5,2.5, 5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 7.5,5.0, 5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 7.5,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 7.5,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 8,5.0, 5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 8,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 8,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 9,5.0, 5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 9,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 9,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 10.5,5.0, 5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 10.5,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 10.5,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 11,5.0, 5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 11,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 11,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 12.5,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 12.5,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 14.5,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 14.5,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 16.0,5.0, 7.5, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], [ 16.0,5.0, 10, 1, [], "http://www.vishay.com/docs/28535/vy2series.pdf"], ] script3mkt="CQ_params_C_Disc.py" for c in caps: seriesname = "Disc"; type = "disc" w = c[0]; d = c[1]; w2 = 0; rm = c[2]; ddrill = c[3]; add_description = c[5]; name_additions = c[4] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=d, ddrill=ddrill, R_POW=R_POW, type=type, w2=w2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=specialtags, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=script3mkt) ########################################################### # axial capacitors ########################################################### scriptaxh="CQ_params_C_Axial.py" with open(scriptaxh, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") d2=0 seriesname = "Axial"; w = 3.8; d = 2.6; ddrill = 0.8; R_POW = 0; add_description = "http://www.vishay.com/docs/45231/arseries.pdf"; name_additions = [] for rm in [7.5, 10, 12.5, 15]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=scriptaxh) seriesname = "Axial"; w = 5.1; d = 3.1; ddrill = 0.8; R_POW = 0; add_description = "http://www.vishay.com/docs/45231/arseries.pdf"; name_additions = [] for rm in [7.5, 10, 12.5, 15]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=scriptaxh) for w in [12,17,19,22]: if w == 12: rms = [15, 20] ds=[6.5,7.5,8.5,9.5,10.5] if w == 17: rms = [20, 25] ds=[6.5,7.0] if w == 19: rms = [25] ds=[7.5, 8.0, 9, 9.5] if w == 22: rms = [27.5] ds=[9.5,10.5] for d in ds: for rm in rms: seriesname = "Axial"; ddrill = 0.8; R_POW = 0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B300/STYROFLEX.pdf"; name_additions = [] makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=scriptaxh) seriesname = "Axial"; w = 12; d = 6.5; ddrill = 0.8; R_POW = 0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B300/STYROFLEX.pdf"; name_additions = [] for rm in [15,20]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=scriptaxh) seriesname = "Axial"; w = 12; d = 7.5; ddrill = 0.8; R_POW = 0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B300/STYROFLEX.pdf"; name_additions = [] for rm in [15,20]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=scriptaxh) seriesname = "Axial"; w = 12; d = 8.5; ddrill = 0.8; R_POW = 0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B300/STYROFLEX.pdf"; name_additions = [] for rm in [15,20]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=scriptaxh) seriesname = "Axial"; w = 12; d = 9.5; ddrill = 0.8; R_POW = 0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B300/STYROFLEX.pdf"; name_additions = [] for rm in [15,20]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", script3d=scriptaxh) ########################################################### # tantal polarized capacitors ########################################################### specialtags=["Tantal Electrolytic Capacitor"] # d rm ddrill name_additions add_description caps = [ [ 4.5, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 4.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 5.0, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 5.0, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 5.5, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 5.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 6.0, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 6.0, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 7.0, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 7.0, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 8.0, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 8.0, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 9.0, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 9.0, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 10.5, 2.5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], [ 10.5, 5, 0.8, [], "http://cdn-reichelt.de/documents/datenblatt/B300/TANTAL-TB-Serie%23.pdf"], ] scripttan="CQ_params_CP_Tantal.py" with open(scripttan, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") for c in caps: seriesname = "Radial_Tantal"; type = "round" deco="tantal" d = c[0]; w2 = 0; rm = c[1]; ddrill = c[2]; add_description = c[4]; name_additions = c[3] makeResistorRadial(seriesname=seriesname, rm=rm, w=d, h=d, ddrill=ddrill, R_POW=R_POW, type=type, w2=w2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=specialtags, classname="CP", lib_name="${KISYS3DMOD}/Capacitor_THT", deco=deco, script3d=scripttan) ########################################################### # radial electrolytic capacitors ########################################################### specialtags = ["Electrolytic Capacitor"] # d h, rm rm2, ddrill name_additions specialtags add_description caps = [ [4, 7, 1.5, 0, 0.6, [], [], ""], [4, 7, 2, 0, 0.6, [], [], ""], [5, 7, 2, 0, 0.8, [], [], ""], [5, 7, 2.5, 0, 0.8, [], [], ""], [6.3, 7, 2.5, 0, 0.8, [], [], ""], [7.5, 8, 2.5, 0, 0.8, [], [], ""], [8, 10, 2.5, 0, 0.8, [], [], ""], [8, 12, 3.5, 0, 0.8, [], [], ""], [8, 14, 3.8, 0, 0.8, [], [], ""], [8, 16, 5, 0, 0.8, [], [], ""], [10, 16, 3.5, 0, 1, [], [], ""], [10, 16, 3.8, 0, 1, [], [], ""], [10, 16, 5, 0, 1, [], [], ""], [10, 16, 5, 7.5, 1, [], [], ""], [10, 20, 7.5, 0, 1, [], [], ""], [10, 12, 2.5, 0, 0.8, [], [], ""], [10, 12, 2.5, 5, 0.8, [], [], ""], [12.5, 20, 5, 0, 1.2, [], [], ""], [12.5, 24, 7.5, 0, 1.2, [], [], ""], [12.5, 16, 2.5, 0, 1.2, [], [], ""], [13, 20, 5, 0, 1.2, [], [], ""], [13, 24, 7.5, 0, 1.2, [], [], ""], [13, 16, 2.5, 0, 1.2, [], [], ""], [14, 20, 5, 0, 1.2, [], [], ""], [14, 20, 7.5, 0, 1.2, [], [], ""], [16, 25, 7.5, 0, 1.2, [], [], ""], [17, 30, 7.5, 0, 1.2, [], [], ""], [18, 35, 7.5, 0, 1.2, [], [], ""], [22, 40, 10, 0, 2, ["SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [24, 40, 10, 0, 2, ["SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [25, 45, 10, 0, 2, ["SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [26, 50, 10, 0, 2, ["SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [30, 50, 10, 0, 2, ["SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [35, 50, 10, 0, 2, ["SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [40, 50, 10, 0, 2, ["SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], ] scriptcprad = "CQ_params_CP_Radial.py" with open(scriptcprad, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") for c in caps: seriesname = "Radial"; type = "round" deco = "elco" d = c[0]; h3d = c[1] w2 = 0; rm = c[2]; rm2 = c[3] ddrill = c[4]; add_description = c[7]; name_additions = c[5] special_tags = specialtags + c[6] makeResistorRadial(seriesname=seriesname, rm=rm, rm2=rm2, w=d, h=d, ddrill=ddrill, R_POW=R_POW, type=type, w2=w2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=special_tags, classname="CP", lib_name="${KISYS3DMOD}/Capacitor_THT", deco=deco, script3d=scriptcprad, height3d=h3d) ########################################################### # radial nonpolar electrolytic capacitors # package sizes taken from: # http://nichicon-us.com/english/products/pdfs/e-ump.pdf # http://nichicon-us.com/english/products/pdfs/e-usp.pdf # http://nichicon-us.com/english/products/pdfs/e-uvp.pdf # http://nichicon-us.com/english/products/pdfs/e-ues.pdf ########################################################### specialtags = ["Non-Polar Electrolytic Capacitor"] # d h, rm rm2, ddrill name_additions specialtags add_description caps = [ [4, 5, 1.5, 0, 0.6, [], [], ""], [4, 7, 1.5, 0, 0.6, [], [], ""], [5, 5, 2, 0, 0.6, [], [], ""], [5, 7, 2, 0, 0.6, [], [], ""], [5, 11, 2, 0, 0.8, [], [], ""], [6.3, 5, 2.5, 0, 0.8, [], [], ""], [6.3, 7, 2.5, 0, 0.8, [], [], ""], [6.3, 11, 2.5, 0, 0.8, [], [], ""], [8, 7, 3.5, 0, 0.8, [], [], ""], [8, 11.5, 3.5, 0, 0.8, [], [], ""], [10, 12.5, 5, 0, 0.8, [], [], ""], [10, 16, 5, 0, 0.8, [], [], ""], [10, 20, 5, 0, 0.8, [], [], ""], [12.5, 20, 5, 0, 0.8, [], [], ""], [12.5, 25, 5, 0, 0.8, [], [], ""], [16, 25, 7.5, 0, 1, [], [], ""], [16, 31.5, 7.5, 0, 1, [], [], ""], [18, 35.5, 7.5, 0, 1, [], [], ""] ] scriptcprad = "CQ_params_C_Radial.py" with open(scriptcprad, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") for c in caps: seriesname = "Radial"; type = "round" deco = "electrolytic nonpolar" d = c[0]; h3d = c[1] w2 = 0; rm = c[2]; rm2 = c[3] ddrill = c[4]; add_description = c[7]; name_additions = c[5] special_tags = specialtags + c[6] makeResistorRadial(seriesname=seriesname, rm=rm, rm2=rm2, w=d, h=d, ddrill=ddrill, R_POW=R_POW, type=type, w2=w2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=special_tags, classname="C", lib_name="${KISYS3DMOD}/Capacitor_THT", deco=deco, script3d=scriptcprad, height3d=h3d) ########################################################### # radial electrolytic capacitors, 3 pins ########################################################### specialtags = ["Electrolytic Capacitor"] # p3= [pinid, posx, posy, ddrill] # d h, rm p3, ddrill name_additions specialtags add_description caps = [ [ 22, 40, 10, [2,10-3.3,-4.75,2.5], 2, ["3pin", "SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [ 24, 40, 10, [2,10-3.3,-4.75,2.5], 2, ["3pin", "SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [ 25, 45, 10, [2,10-3.3,-4.75,2.5], 2, ["3pin", "SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [ 26, 45, 10, [2,10-3.3,-4.75,2.5], 2, ["3pin", "SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [ 30, 45, 10, [2,10-3.3,-4.75,2.5], 2, ["3pin", "SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [ 35, 50, 10, [2,10-3.3,-4.75,2.5], 2, ["3pin", "SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], [ 40, 50, 10, [2,10-3.3,-4.75,2.5], 2, ["3pin", "SnapIn"], [], ", http://www.vishay.com/docs/28342/058059pll-si.pdf"], ] scriptcprad3p = "CQ_params_CP_Radial_3Pin.py" with open(scriptcprad3p, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") for c in caps: seriesname = "Radial"; type = "round" deco = "elco" d = c[0]; h3d = c[1] w2 = 0; rm = c[2]; rm2 = 0 ddrill = c[4]; add_description = c[7]; name_additions = c[5] special_tags = specialtags + c[6] ap=[c[3]] makeResistorRadial(seriesname=seriesname, rm=rm, rm2=rm2, w=d, h=d, ddrill=ddrill, R_POW=R_POW, type=type, w2=w2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=special_tags, classname="CP", lib_name="${KISYS3DMOD}/Capacitor_THT", deco=deco, script3d=scriptcprad3p, height3d=h3d, additionalPins=ap) ########################################################### # axial electrolytic capacitors ########################################################### specialtags = ["Electrolytic Capacitor"] # d l rm ddrill name_additions specialtags add_description caps = [ [ 4.5, 10, 15, 1, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 6, 10, 15, 1, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 8, 11, 15, 1, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 6.5, 18, 25, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 8, 18, 25, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 10, 18, 25, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 10, 25, 30, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 10, 30, 35, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 12.5, 30, 35, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 15, 30, 35, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 18, 30, 35, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 18, 38, 44, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 21, 38, 44, 1.2, [], [], ", http://www.vishay.com/docs/28325/021asm.pdf"], [ 23.0, 42, 45, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 23.0, 55, 60, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 23.0, 67, 75, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 23.0, 80, 85, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 23.0, 93, 100, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 26, 42, 45, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 26, 55, 60, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 26, 67, 75, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 26, 80, 85, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 26, 93, 100, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 29.0, 42, 45, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 29.0, 55, 60, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 29.0, 67, 75, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 29.0, 80, 85, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 29.0, 93, 100, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 32.0, 42, 45, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 32.0, 55, 60, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 32.0, 67, 75, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 32.0, 80, 85, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 32.0, 93, 100, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 35.0, 42, 45, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 35.0, 55, 60, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 35.0, 67, 75, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 35.0, 80, 85, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 35.0, 93, 100, 1.2, [], [], ", http://www.vishay.com/docs/42037/53d.pdf"], [ 10, 20, 26, 1.2, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 10, 29, 35, 1.2, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 13, 20, 26, 1.2, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 13, 29, 35, 1.2, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 13, 37, 43, 1.2, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 16, 29, 35, 1.2, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 16, 37, 43, 1.2, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 16, 40, 48, 1.2, [], [], ""], [ 20, 26.5, 33, 1.4, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 20, 29, 35, 1.4, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 20, 34.5, 41, 1.4, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 20, 37, 43, 1.4, [], [], ", http://www.kemet.com/Lists/ProductCatalog/Attachments/424/KEM_AC102.pdf"], [ 20, 42.5, 49, 1.4, [], [], ""], [ 20, 46, 52, 1.4, [], [], ""], [ 5, 11, 18, 1.2, [], [], ""], [ 6, 11, 18, 1.2, [], [], ""], [ 8, 21, 28, 1.2, [], [], ""], ] scriptcpax="CQ_params_CP_Axial.py" with open(scriptcpax, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") for c in caps: seriesname = "Axial"; type = "cyl" deco = "elco" d = c[0]; l = c[1]; rm = c[2] ddrill = c[3]; add_description = c[6]; name_additions = c[4] special_tags = specialtags + c[5] makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=l, d=d, ddrill=ddrill, R_POW=R_POW, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=special_tags, classname="CP", lib_name="${KISYS3DMOD}/Capacitor_THT", deco=deco, script3d=scriptcpax) ================================================ FILE: scripts/Chokes_THT/make_Chokes_THT.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_resistorlike import * if __name__ == '__main__': # standard resistors: http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf type = "cyl" d2=0 script3d="L_Choke_axial_cyl_hor.py" with open(script3d, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dv="L_Choke_axial_cyl_ver.py" with open(script3dv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") # axial Chokes classname="L" libname = "${KISYS3DMOD}/Inductor_THT" seriesname = "Axial"; w = 9.5; d = 4; ddrill = 1; R_POW = 0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/DS_SMCC_NEU.pdf, http://cdn-reichelt.de/documents/datenblatt/B400/LEADEDINDUCTORS.pdf"; name_additions=["Fastron","SMCC"] for rm in [12.7,15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [2.54,5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 7; d = 3.3; ddrill = 0.8; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/70/MICC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","MICC"] for rm in [10.16,12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [2.54,5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 24; d = 7.5; ddrill = 1.2; R_POW = 0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/DS_MESC.pdf"; name_additions=["Fastron","MESC"] for rm in [27.94]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 16; d = 7.5; ddrill = 1.1; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/26/XHBCC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","XHBCC"] for rm in [20.32,25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 16; d = 6.3; ddrill = 1.1; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/25/VHBCC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","VHBCC"] for rm in [20.32,25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 14.5; d = 5.8; ddrill = 1.1; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/18/HBCC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","HBCC"] for rm in [20.32,25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 12.8; d = 5.8; ddrill = 1.1; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/18/HBCC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","HBCC"] for rm in [20.32,25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 12; d = 5; ddrill = 1.2; R_POW = 0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/DS_MISC.pdf"; name_additions=["Fastron","MISC"] for rm in [15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 11; d = 4.5; ddrill = 1.0; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/21/MECC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","MECC"] for rm in [15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 13; d = 4.5; ddrill = 1.2; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/19/HCCC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","HCCC"] for rm in [15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 14; d = 4.5; ddrill = 1.0; R_POW = 0; add_description="http://www.fastrongroup.com/image-show/20/LACC.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron","LACC"] for rm in [15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 20; d = 8; ddrill = 1.2; R_POW = 0; add_description=""; name_additions=[] for rm in [25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 30; d = 8; ddrill = 1.4; R_POW = 0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/DS_77A.pdf"; name_additions=["Fastron","77A"] for rm in [35.56]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 26; d = 9; ddrill = 1.2; R_POW = 0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/DS_77A.pdf"; name_additions=["Fastron","77A"] for rm in [30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 26; d = 10; ddrill = 1.2; R_POW = 0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/DS_77A.pdf"; name_additions=["Fastron","77A"] for rm in [30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 26; d = 11; ddrill = 1.2; R_POW = 0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/DS_77A.pdf"; name_additions=["Fastron","77A"] for rm in [30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 5.3; d = 2.2; ddrill = 0.8; R_POW = 0; add_description="http://www.vishay.com/docs/34030/im.pdf"; name_additions=["Vishay","IM-1"] for rm in [7.62,10.16]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [2.54]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 6.6; d = 2.7; ddrill = 0.8; R_POW = 0; add_description="http://www.vishay.com/docs/34030/im.pdf"; name_additions=["Vishay","IM-2"] for rm in [10.16]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [2.54]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 24; d = 7.1; ddrill = 1.0; R_POW = 0; add_description="http://www.vishay.com/docs/34035/im10.pdf"; name_additions=["Vishay","IM-10-28"] for rm in [30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 24; d = 7.1; ddrill = 1.0; R_POW = 0; add_description="http://www.vishay.com/docs/34035/im10.pdf"; name_additions=["Vishay","IM-10-28"] for rm in [30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 16; d = 9.5; ddrill = 1; R_POW = 0; add_description="http://www.vishay.com/docs/34030/im10.pdf"; name_additions=["Vishay","IM-10-37"] for rm in [20.32]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 17.5; d = 12; ddrill = 1; R_POW = 0; add_description="http://www.vishay.com/docs/34030/im10.pdf"; name_additions=["Vishay","IM-10-46"] for rm in [20.32]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 20.32; d = 12.07; ddrill = 1.2; R_POW = 0; add_description="http://www.vishay.com/docs/34014/iha.pdf"; name_additions=["Vishay","IHA-101"] for rm in [28.5]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 26.67; d = 12.07; ddrill = 1.2; R_POW = 0; add_description="http://www.vishay.com/docs/34014/iha.pdf"; name_additions=["Vishay","IHA-103"] for rm in [35]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 26.67; d = 13.97; ddrill = 1.2; R_POW = 0; add_description="http://www.vishay.com/docs/34014/iha.pdf"; name_additions=["Vishay","IHA-104"] for rm in [35]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 29.85; d = 13.97; ddrill = 1.2; R_POW = 0; add_description="http://www.vishay.com/docs/34014/iha.pdf"; name_additions=["Vishay","IHA-105"] for rm in [38]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 23.37; d = 12.7; ddrill = 1.2; R_POW = 0; add_description="http://www.vishay.com/docs/34014/iha.pdf"; name_additions=["Vishay","IHA-203"] for rm in [32]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) seriesname = "Axial"; w = 20.32; d = 12.7; ddrill = 1.2; R_POW = 0; add_description="http://www.vishay.com/docs/34014/iha.pdf"; name_additions=["Vishay","IHA-201"] for rm in [25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=name_additions, classname=classname, lib_name=libname, script3d=script3dv) # radial Chokes rm2=0; w2=0 type = "round"; seriesname = "Radial"; classname = "L" libname = "${KISYS3DMOD}/Inductor_THT" script3drbox="L_Choke_radial_box.py" with open(script3drbox, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3drrs="L_Choke_radial_round_simple.py" with open(script3drrs, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3drro="L_Choke_radial_round_open.py" with open(script3drro, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") w = 12.5; w2=w; h = w; ddrill = 1.2; rm=9.0; rm2=0; R_POW=0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B400/DS_09HCP.pdf"; name_additions=["Fastron", "09HCP"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.8, script3d=script3drro) w = 12.5; w2=w; h = w; ddrill = 1.2; rm=7.0; rm2=0; R_POW=0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B400/DS_09HCP.pdf"; name_additions=["Fastron", "09HCP"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.8, script3d=script3drro) w = 13.5; w2=w; h = w; ddrill = 1.2; rm=7.0; rm2=0; R_POW=0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B400/DS_09HCP.pdf"; name_additions=["Fastron", "09HCP"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.8, script3d=script3drro) w = 12.0; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B400/DS_11P.pdf"; name_additions=["Fastron", "11P"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=16, script3d=script3drrs) w = 12.0; w2=w; h = w; ddrill = 1.6; rm=6.0; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1900r.pdf"; name_additions=["MuRATA", "1900R"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21, script3d=script3drrs) w = 7.2; w2=w; h = w; ddrill = 1.2; rm=3.0; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1700.pdf"; name_additions=["MuRATA", "1700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=8.5, script3d=script3drrs) w = 10.5; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.abracon.com/Magnetics/radial/AISR-01.pdf"; name_additions=["Abacron", "AISR-01"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drrs) w = 10; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.fastrongroup.com/image-show/37/07M.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron", "07M"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=12.7, script3d=script3drro) w = 8.7; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://cdn-reichelt.de/documents/datenblatt/B400/DS_07HCP.pdf"; name_additions=["Fastron", "07HCP"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10, script3d=script3drro) w = 7.8; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.abracon.com/Magnetics/radial/AISR875.pdf"; name_additions=["Fastron", "07HCP"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=7.5, script3d=script3drrs) w = 7.5; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.fastrongroup.com/image-show/39/07P.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron", "07P"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=12.5, script3d=script3drro) w = 7.5; w2=w; h = w; ddrill = 1.3; rm=3.5; rm2=0; R_POW=0; add_description = "http://www.fastrongroup.com/image-show/39/07P.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron", "07P"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=12.5, script3d=script3drro) w = 9.5; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.fastrongroup.com/image-show/107/07HVP%2007HVP_T.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron", "07HVP"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10, script3d=script3drro) w = 10; w2=w; h = w; ddrill = 1.3; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.fastrongroup.com/image-show/37/07M.pdf?type=Complete-DataSheet&productType=series"; name_additions=["Fastron", "07P"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=12.5, script3d=script3drro) w = 7; w2=w; h = w; ddrill = 1.3; rm=3.0; rm2=0; R_POW=0; add_description = "http://www.abracon.com/Magnetics/radial/AIUR-16.pdf"; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.5, script3d=script3drro) w = 6.0; w2=w; h = w; ddrill = 1; rm=4.0; rm2=0; R_POW=0; add_description = "http://www.abracon.com/Magnetics/radial/AIUR-07.pdf"; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=4.6, script3d=script3drro) w = 18; w2=w; h = w; ddrill = 1; rm=10.0; rm2=0; R_POW=0; add_description = "http://www.abracon.com/Magnetics/radial/AIUR-15.pdf"; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=1.5*w, script3d=script3drrs) w = 21; w2=w; h = w; ddrill = 1; rm=19.0; rm2=0; R_POW=0; add_description = "http://www.abracon.com/Magnetics/radial/AIRD02.pdf"; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21, script3d=script3drrs) w = 24; w2=w; h = w; ddrill = 1.5; rm=24.0; rm2=0; R_POW=0; add_description = ""; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=24, script3d=script3drrs) w = 28; w2=w; h = w; ddrill = 1.5; rm=29.2; rm2=0; R_POW=0; add_description = ""; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=28, script3d=script3drrs) type = "concentric"; script3drconc="L_Choke_radial_concentric.py" with open(script3drconc, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") w = 24.4; w2=5.5; h = w; ddrill = 2.6; rm=23.9; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 24.4; w2=5.5; h = w; ddrill = 2.1; rm=23.7; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 24.4; w2=5.5; h = w; ddrill = 1.5; rm=23.4; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 24.4; w2=5.5; h = w; ddrill = 1.0; rm=23.1; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 24.4; w2=5.5; h = w; ddrill = 0.8; rm=22.9; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 29.8; w2=5.1; h = w; ddrill = 2.6; rm=29.3; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 29.8; w2=5.1; h = w; ddrill = 2.0; rm=29; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 29.8; w2=5.1; h = w; ddrill = 1.5; rm=28.8; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 29.8; w2=5.1; h = w; ddrill = 1; rm=28.5; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 29.8; w2=5.1; h = w; ddrill = 0.8; rm=28.3; rm2=0; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_1400.pdf"; name_additions=["muRATA", "1400series"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drconc) w = 16.8; w2=2.92; h = w; ddrill = 1.4; rm=11.43; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-1"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 16.8; w2=2.92; h = w; ddrill = 1.0; rm=12.07; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-1"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 16.8; w2=2.92; h = w; ddrill = 1.0; rm=12.70; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-1"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 21; w2=2.92; h = w; ddrill = 1.6; rm=15.75; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-2"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 21; w2=2.92; h = w; ddrill = 1.3; rm=14.61; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-2"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 21; w2=2.92; h = w; ddrill = 1.2; rm=15.24; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-2"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 21; w2=2.92; h = w; ddrill = 0.8; rm=15; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-2"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 27.9; w2=2.92; h = w; ddrill = 2.1; rm=20.07; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 27.9; w2=2.92; h = w; ddrill = 1.8; rm=19.05; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 27.9; w2=2.92; h = w; ddrill = 1.8; rm=18.29; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.34, script3d=script3drconc) w = 40.64; w2=4.45; h = w; ddrill = 2.2; rm=27.94; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-4"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=26.16, script3d=script3drconc) w = 40.64; w2=4.45; h = w; ddrill = 1; rm=27.18; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-4"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=26.16, script3d=script3drconc) w = 40.64; w2=4.45; h = w; ddrill = 2.4; rm=28.70; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-5"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=36.83, script3d=script3drconc) w = 40.64; w2=4.45; h = w; ddrill = 2.2; rm=27.94; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-5"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=36.83, script3d=script3drconc) w = 40.64; w2=4.45; h = w; ddrill = 1.3; rm=26.16; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-5"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=36.83, script3d=script3drconc) w = 50.80; w2=4.45; h = w; ddrill = 2.9; rm=36.32; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-6"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=38.10, script3d=script3drconc) w = 50.80; w2=6.10; h = w; ddrill = 2.9; rm=38.86; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-6"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=38.10, script3d=script3drconc) w = 50.80; w2=6.10; h = w; ddrill = 2.1; rm=35.81; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-6"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=38.10, script3d=script3drconc) w = 50.80; w2=6.10; h = w; ddrill = 1.9; rm=34.29; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-6"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=38.10, script3d=script3drconc) w = 50.80; w2=6.10; h = w; ddrill = 1.6; rm=33.27; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34015/ihb.pdf"; name_additions=["Vishay", "IHB-6"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=38.10, script3d=script3drconc) type = "simplesymm45"; w = 9.14; w2=w; h = w; ddrill = 1; rm=6.35; rm2=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-54044NL-Pulse-datasheet-5313493.pdf"; name_additions=["Pulse", "LP-25"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=7.87, script3d=script3drbox) w = 10.16; w2=w; h = w; ddrill = 1; rm=7.62; rm2=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-54044NL-Pulse-datasheet-5313493.pdf"; name_additions=["Pulse", "LP-30"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=7.62, script3d=script3drbox) w = 12.57; w2=w; h = w; ddrill = 1; rm=9.52; rm2=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-54044NL-Pulse-datasheet-5313493.pdf"; name_additions=["Pulse", "LP-37"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.52, script3d=script3drbox) w = 16.13; w2=w; h = w; ddrill = 1; rm=7.62; rm2=12.7; R_POW=0; add_description = "http://datasheet.octopart.com/PE-54044NL-Pulse-datasheet-5313493.pdf"; name_additions=["Pulse", "LP-44"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.27, script3d=script3drbox) rm2=0; w2=0 type = "round"; classname = "L_Toroid" libname = "${KISYS3DMOD}/Inductor_THT" deco="chokewire" type = "concentric" ;seriesname = "Horizontal"; script3dtoroidhor="L_Choke_toroid_hor.py" with open(script3dtoroidhor, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") w = 40; w2=w/3; h = w; ddrill = 1.5; rm=48.26; rm2=0; R_POW=0; add_description = ""; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=4, script3d=script3dtoroidhor) w = 0.125*25.4; w2=0.062*25.4; h = w; ddrill = 1; rm=6.4; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter3-5mm","Amidon-T12"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=4, script3d=script3dtoroidhor) w = 0.160*25.4; w2=0.078*25.4; h = w; ddrill = 1; rm=8; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter4-5mm","Amidon-T16"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=4, script3d=script3dtoroidhor) w = 0.200*25.4; w2=0.088*25.4; h = w; ddrill = 1; rm=9; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter6-5mm","Amidon-T20"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=4.5, script3d=script3dtoroidhor) w = 0.255*25.4; w2=0.120*25.4; h = w; ddrill = 1; rm=10; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter7-5mm","Amidon-T25"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=5, script3d=script3dtoroidhor) w = 0.307*25.4; w2=0.151*25.4; h = w; ddrill = 1.2; rm=13; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter9-5mm","Amidon-T30"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=5.5, script3d=script3dtoroidhor) w = 0.375*25.4; w2=0.205*25.4; h = w; ddrill = 1.2; rm=15; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter10-5mm","Amidon-T37"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=6, script3d=script3dtoroidhor) w = 0.440*25.4; w2=0.229*25.4; h = w; ddrill = 1.2; rm=17; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter12-5mm","Amidon-T44"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=6.5, script3d=script3dtoroidhor) w = 0.500*25.4; w2=0.303*25.4; h = w; ddrill = 1.2; rm=20; rm2=0; R_POW=0; add_description = ""; name_additions=["Diameter14-5mm","Amidon-T50"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=7, script3d=script3dtoroidhor) w = 16.8; w2=w/3; h = w; ddrill = 1.5; rm=14.7; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ3", "BigPads"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=8.2, script3d=script3dtoroidhor) w = 16.8; w2=w/3; h = w; ddrill = 1.2; rm=14.7; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=8.2, script3d=script3dtoroidhor) w = 17.3; w2=w/3; h = w; ddrill = 1.8; rm=15.24; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2000_series.pdf?sfvrsn=5"; name_additions=["Bourns", "2000"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.4, script3d=script3dtoroidhor) w = 21.8; w2=w/3; h = w; ddrill = 1.8; rm=19.6; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2100_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2100"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.4, script3d=script3dtoroidhor) w = 21.8; w2=w/3; h = w; ddrill = 1.8; rm=19.1; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2100_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2100"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=11.4, script3d=script3dtoroidhor) w = 22.4; w2=w/3; h = w; ddrill = 1.5; rm=19.8; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ4"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.2, script3d=script3dtoroidhor) w = 24.1; w2=w/3; h = w; ddrill = 1.8; rm=21.8; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2100_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2200"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=14, script3d=script3dtoroidhor) w = 24.1; w2=w/3; h = w; ddrill = 1.8; rm=23.1; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2100_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2200"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=14, script3d=script3dtoroidhor) w = 25.4; w2=w/3; h = w; ddrill = 1.5; rm=22.9; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ5", "BigPads"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=11.4, script3d=script3dtoroidhor) w = 25.4; w2=w/3; h = w; ddrill = 1.2; rm=22.9; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ5"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=11.4, script3d=script3dtoroidhor) w = 28; w2=w/3; h = w; ddrill = 1.5; rm=26.67; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2100_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2200"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=14, script3d=script3dtoroidhor) w = 28; w2=w/3; h = w; ddrill = 1.3; rm=25.1; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2100_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2200"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=14, script3d=script3dtoroidhor) w = 32.5; w2=w/3; h = w; ddrill = 2; rm=30; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2300_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2300"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=16.5, script3d=script3dtoroidhor) w = 32.5; w2=w/3; h = w; ddrill = 1.5; rm=28.9; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/2300_series.pdf?sfvrsn=3"; name_additions=["Bourns", "2300"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=16.5, script3d=script3dtoroidhor) w = 35.1; w2=w/3; h = w; ddrill = 1.5; rm=31.0; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ6"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=21.1, script3d=script3dtoroidhor) w = 41.9; w2=w/3; h = w; ddrill = 1.5; rm=37.6; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ7"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=19.1, script3d=script3dtoroidhor) w = 49.3; w2=w/3; h = w; ddrill = 1.7; rm=44.6; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ8"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=25.4, script3d=script3dtoroidhor) w = 69.1; w2=w/3; h = w; ddrill = 2; rm=63.2; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ9"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=36.1, script3d=script3dtoroidhor) type = "simple90" ;seriesname = "Vertical"; deco="chokewire"; script3dtoroidver="L_Choke_toroid_ver.py" with open(script3dtoroidver, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dtoroidverbox="L_Choke_toroid_ver_box.py" with open(script3dtoroidverbox, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") w = 10; w2=w/3; h = 5; ddrill = 1.0; rm=5.08; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = ""; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 13; w2=w/3; h = 6.5; ddrill = 1.3; rm=5.6; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = ""; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 16; w2=w/3; h = 8; ddrill = 1.5; rm=7.62; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = ""; name_additions=[] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 14.73; w2=w/3; h = 8.64; ddrill = 1.8; rm=2.79*2; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "KM-1"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 16.51; w2=w/3; h = 11.43; ddrill = 1.8; rm=3.81*2; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "KM-2"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 21.59; w2=w/3; h = 11.43; ddrill = 1.8; rm=3.81*2; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "KM-3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 24.64; w2=w/3; h = 15.5; ddrill = 1.8; rm=5.72*2; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "KM-4"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 33.02; w2=w/3; h = 17.78; ddrill = 1.8; rm=6.35*2; rm2=0; iw=w*0.8; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "KM-5"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidverbox) w = 13.97; w2 = w / 3; h = 6.35; ddrill = 1.5; rm = 4.57; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "A"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 17.78; w2 = w / 3; h = 9.65; ddrill = 1.5; rm = 7.11; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "B"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 21.59; w2 = w / 3; h = 9.53; ddrill = 1.8; rm = 7.11; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "C"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 26.67; w2 = w / 3; h = 13.97; ddrill = 1.8; rm = 10.16; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "D"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 35.56; w2 = w / 3; h = 17.78; ddrill = 1.8; rm = 12.7; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "E"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 41.91; w2 = w / 3; h = 17.78; ddrill = 1.8; rm = 12.7; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "F"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 21.59; w2 = w / 3; h = 8.38; ddrill = 1.5; rm = 8.38; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "G"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 16.26; w2 = w / 3; h = 7.11; ddrill = 1.5; rm = 7.11; R_POW=0; add_description = "http://datasheet.octopart.com/PE-92112KNL-Pulse-datasheet-17853305.pdf"; name_additions=["Pulse", "H"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 16.4; w2=w/3; h = 7.6; ddrill = 1.2; rm=6.6; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 16.8; w2=w/3; h = 9.2; ddrill = 1.5; rm=7.1; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ3", "BigPads"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 16.8; w2=w/3; h = 9.2; ddrill = 1.2; rm=7.1; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 22.4; w2=w/3; h = 10.2; ddrill = 1.5; rm=7.9; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ4"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 25.4; w2=w/3; h = 14.7; ddrill = 1.5; rm=12.2; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ5", "BigPads"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 25.4; w2=w/3; h = 14.7; ddrill = 1.2; rm=12.2; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ5"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 35.1; w2=w/3; h = 21.1; ddrill = 1.5; rm=18.5; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ6"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 41.9; w2=w/3; h = 19.1; ddrill = 1.5; rm=15.8; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ7"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 48.8; w2=w/3; h = 25.4; ddrill = 1.7; rm=20.8; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ8"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 67.6; w2=w/3; h = 36.1; ddrill = 2; rm=31.8; rm2=0; R_POW=0; add_description = "http://www.vishay.com/docs/34079/tj.pdf"; name_additions=["Vishay", "TJ9"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 28.6; w2=w/3; h = 14.3; ddrill = 1.8; rm=11.43; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 31.8; w2=w/3; h = 15.9; ddrill = 1.8; rm=13.5; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 46; w2=w/3; h = 19.1; ddrill = 1.9; rm=21.8; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 54; w2=w/3; h = 23.8; ddrill = 1.8; rm=20.1; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 14; w2=w/3; h = 5.6; ddrill = 0.8; rm=5.3; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 17.8; w2=w/3; h = 8.1; ddrill = 0.9; rm=7.62; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 19.1; w2=w/3; h = 8.1; ddrill = 0.8; rm=7.1; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) w = 21.6; w2=w/3; h = 9.1; ddrill = 1.1; rm=8.4; rm2=0; R_POW=0; add_description = "http://www.bourns.com/docs/Product-Datasheets/5700_series.pdf"; name_additions=["Bourns", "5700"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=w, script3d=script3dtoroidver) type = "simple"; classname = "L_CommonMode_Toroid" script3dtoroidver4pin = "L_Choke_toroid_ver_box_4pin.py" with open(script3dtoroidver4pin, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") w = 0.76*25.4; w2=w/3; h = 0.425*25.4; ddrill = 1.5; rm=0.25*25.4; rm2=0.6*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 1.2*25.4; w2=w/3; h = 0.6*25.4; ddrill = 1.5; rm=0.4*25.4; rm2=0.8*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 1.35*25.4; w2=w/3; h = 0.8*25.4; ddrill = 1.5; rm=0.6*25.4; rm2=0.9*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 1.45*25.4; w2=w/3; h = 0.8*25.4; ddrill = 1.5; rm=0.6*25.4; rm2=0.9*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 1.50*25.4; w2=w/3; h = 0.8*25.4; ddrill = 1.8; rm=0.6*25.4; rm2=0.9*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 1.55*25.4; w2=w/3; h = 0.8*25.4; ddrill = 1.5; rm=0.6*25.4; rm2=0.9*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 1.65*25.4; w2=w/3; h = 0.8*25.4; ddrill = 1.5; rm=0.6*25.4; rm2=0.9*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 1.7*25.4; w2=w/3; h = 0.9*25.4; ddrill = 2.2; rm=0.7*25.4; rm2=1.2*25.4; iw=w; ih=rm; R_POW=0; add_description = "http://datasheet.octopart.com/8120-RC-Bourns-datasheet-10228452.pdf"; name_additions=["Bourns", "8100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 21; w2=w/3; h = 10; ddrill = 1.1; rm=5.08; rm2=12.7; iw=w; ih=rm; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_5100.pdf"; name_additions=["muRATA", "5100"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) w = 24; w2=w/3; h = 16.3; ddrill = 1.1; rm=10.16; rm2=20.32; iw=w; ih=rm; R_POW=0; add_description = "http://www.murata-ps.com/data/magnetics/kmp_5200.pdf"; name_additions=["muRATA", "5200"] makeResistorRadial(pins=4, seriesname=seriesname, rm=rm, w=w, h=h, innerw=iw, innerh=ih, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, deco=deco, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=31, script3d=script3dtoroidver4pin) rm2=0; w2=0 type = "round"; seriesname = "Radial"; deco="" classname = "L" libname = "${KISYS3DMOD}/Inductor_THT" w = 12.0; w2=w; h = w; ddrill = 1.2; rm=10.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd12k.pdf"; name_additions=["Neosid", "SD12k", "style1"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=13, script3d=script3drrs) w = 12.0; w2=w; h = w; ddrill = 1.2; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd12k.pdf"; name_additions=["Neosid", "SD12k", "style2"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=13, script3d=script3drrs) w = 10.0; w2=w; h = w; ddrill = 1.2; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd12k.pdf"; name_additions=["Neosid", "SD12k", "style3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=12.5, script3d=script3drrs) w = 12.0; w2=w; h = w; ddrill = 1.2; rm=10.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd12.pdf"; name_additions=["Neosid", "SD12", "style1"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=20, script3d=script3drrs) w = 12.0; w2=w; h = w; ddrill = 1.2; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd12.pdf"; name_additions=["Neosid", "SD12", "style2"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=20, script3d=script3drrs) w = 10.0; w2=w; h = w; ddrill = 1.2; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd12.pdf"; name_additions=["Neosid", "SD12", "style3"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=19.5, script3d=script3drrs) w = 14.2; w2=w; h = w; ddrill = 1.2; rm=10.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd14.pdf"; name_additions=["Neosid", "SD14"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=24.5, script3d=script3drrs) type = "simple"; w = 7.5; w2=w; h = 4.6; ddrill = 0.8; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd75.pdf"; name_additions=["Neosid", "SD75"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=10.5, script3d=script3drbox) w = 8; w2=w; h = 8; ddrill = 0.8; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_Sd8.pdf"; name_additions=["Neosid", "SD8"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.6, script3d=script3drbox) w = 8; w2=w; h = 8; ddrill = 1.2; rm=5.0; rm2=0; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_NE_CPB07E.pdf"; name_additions=["Neosid", "NE-CPB-07E"] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=7.5, script3d=script3drbox) type = "simplesymm45"; w = 11.5; w2=w; h = 11.5; ddrill = 1.8; rm=6.0; rm2=6; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_NE_CPB11EN.pdf"; name_additions=["Neosid", "NE-CPB-11EN", "Drill{0:0.1f}mm".format(ddrill)] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.6, script3d=script3drbox) w = 11.5; w2=w; h = 11.5; ddrill = 1.7; rm=6.0; rm2=6; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_NE_CPB11EN.pdf"; name_additions=["Neosid", "NE-CPB-11EN", "Drill{0:0.1f}mm".format(ddrill)] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.6, script3d=script3drbox) w = 11.5; w2=w; h = 11.5; ddrill = 1.5; rm=6.0; rm2=6; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_NE_CPB11EN.pdf"; name_additions=["Neosid", "NE-CPB-11EN", "Drill{0:0.1f}mm".format(ddrill)] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.6, script3d=script3drbox) w = 11.5; w2=w; h = 11.5; ddrill = 1.3; rm=6.0; rm2=6; R_POW=0; add_description = "http://www.neosid.de/produktblaetter/neosid_Festinduktivitaet_NE_CPB11EN.pdf"; name_additions=["Neosid", "NE-CPB-11EN", "Drill{0:0.1f}mm".format(ddrill)] makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1, 1, 1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=name_additions, add_description=add_description, classname=classname, lib_name=libname, height3d=9.6, script3d=script3drbox) ================================================ FILE: scripts/Connector/Connector_Audio/Jack_3.5mm_Switronic_ST-005-G_horizontal.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) from KicadModTree import * datasheet = "http://akizukidenshi.com/download/ds/switronic/ST-005-G.pdf" footprint_name = "Jack_3.5mm_Switronic_ST-005-G_horizontal" baseWidth = 11.5 baseHeight = 6.5 outletHeight = 5.0 outletWidth = 2.5 padHoleSize = 1.2 mountingHoleSize = 1.0 frontPadOffset = 3.5 frontPadSpacing = 5.8 mountingHoleOffset = 7.0 mountingHoleSpacing = 5.0 backPadOffset = 11.0 backPadSpacing = 4.5 f = Footprint(footprint_name) f.setDescription(datasheet) f.setTags("Connector Audio Switronic ST-005-G") f.append(Model(filename="${KISYS3DMOD}/Connector_Audio.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) s = [1.0, 1.0] sFabRef = [0.7, 0.7] t1 = 0.1 t2 = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 crtYdClearance = 0.5 silkClearance = 0.2 padSizeDiffFromHole = 0.7 padSize = [padHoleSize + padSizeDiffFromHole, padHoleSize + padSizeDiffFromHole] padDrill = [padHoleSize, padHoleSize] xCenter = 0.0 xFabBaseLeft = outletWidth - ((baseWidth + outletWidth) / 2) xFrontPad = xFabBaseLeft + frontPadOffset xMountingHole = xFabBaseLeft + mountingHoleOffset xBackPad = xFabBaseLeft + backPadOffset xFabRight = (outletWidth + baseWidth) / 2 xSilkRight = xFabRight + silkClearance xSilkFrontPadRight = xFrontPad + padHoleSize xRightCrtYd = xBackPad + padSize[0] / 2 + crtYdClearance xFabLeft = -xFabRight xLeftCrtYd = xFabLeft - crtYdClearance xSilkBaseLeft = xFabBaseLeft - silkClearance xSilkLeft = -xSilkRight xSilkFrontPadLeft = xFrontPad - padHoleSize xSilkBackPadLeft = xBackPad - padHoleSize yCenter = 0.0 yFrontPadBottom = frontPadSpacing / 2 yMountingHoleBottom = mountingHoleSpacing / 2 yBackPadBottom = backPadSpacing / 2 yFabOutletBottom = outletHeight / 2 yFabBottom = baseHeight / 2 ySilkBottom = yFabBottom + silkClearance ySilkOutletBottom = yFabOutletBottom + silkClearance ySilkBackPadBottom = yBackPadBottom - padHoleSize yBottomCrtYd = yFrontPadBottom + padSize[0] / 2 + crtYdClearance yFrontPadTop = -yFrontPadBottom yMountingHoleTop = -yMountingHoleBottom yBackPadTop = -yBackPadBottom yFabTop = -yFabBottom yFabOutletTop = -yFabOutletBottom ySilkTop = -ySilkBottom ySilkOutletTop = -ySilkOutletBottom ySilkBackPadTop = -ySilkBackPadBottom yTopCrtYd = -yBottomCrtYd yValue = yFabBottom + 1.25 yRef = yFabTop - 1.25 f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s, thickness=t2)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s, thickness=t2)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=sFabRef, thickness=t1)) f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) f.append(Circle(center=[xBackPad, ySilkBackPadTop], radius=0.3, layer="F.Fab")) f.append(PolygoneLine(polygone=[[xFabLeft, yFabOutletTop], [xFabBaseLeft, yFabOutletTop], [xFabBaseLeft, yFabTop], [xFabRight, yFabTop], [xFabRight, yFabBottom], [xFabBaseLeft, yFabBottom], [xFabBaseLeft, yFabOutletBottom], [xFabLeft, yFabOutletBottom], [xFabLeft, yFabOutletTop]], layer="F.Fab", width=wFab)) f.append(PolygoneLine(polygone=[[xSilkFrontPadLeft, ySilkBottom], [xSilkBaseLeft, ySilkBottom], [xSilkBaseLeft, ySilkOutletBottom]], layer="F.SilkS", width=wSilkS)) f.append(PolygoneLine(polygone=[[xSilkBaseLeft, ySilkOutletTop], [xSilkBaseLeft, ySilkTop], [xSilkFrontPadLeft, ySilkTop]], layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xSilkFrontPadRight, ySilkTop], end=[xSilkBackPadLeft, ySilkTop], layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xSilkFrontPadRight, ySilkBottom], end=[xSilkRight, ySilkBottom], layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xSilkRight, ySilkBackPadTop], end=[xSilkRight, ySilkBackPadBottom], layer="F.SilkS", width=wSilkS)) f.append(Pad(number="T", type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[xFrontPad, yFrontPadTop], size=padSize, drill=padDrill, layers=['*.Cu', '*.Mask'])) f.append(Pad(number="T", type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[xFrontPad, yFrontPadBottom], size=padSize, drill=padDrill, layers=['*.Cu', '*.Mask'])) f.append(Pad(number="R", type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[xBackPad, yBackPadTop], size=padSize, drill=padDrill, layers=['*.Cu', '*.Mask'])) f.append(Pad(number="S", type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[xBackPad, yBackPadBottom], size=padSize, drill=padDrill, layers=['*.Cu', '*.Mask'])) f.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[xMountingHole, yMountingHoleBottom], size=mountingHoleSize, drill=mountingHoleSize, layers=Pad.LAYERS_NPTH)) f.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[xMountingHole, yMountingHoleTop], size=mountingHoleSize, drill=mountingHoleSize, layers=Pad.LAYERS_NPTH)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") ================================================ FILE: scripts/Connector/Connector_Harwin/conn_harwin_m20-781xx45_smd_top_dual_row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml #from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'M20' series_long = 'Female Vertical Surface Mount Double Row 2.54mm (0.1 inch) Pitch PCB Connector' manufacturer = 'Harwin' datasheet = 'https://cdn.harwin.com/pdfs/M20-781.pdf' # https://cdn.harwin.com/pdfs/Harwin_Product_Catalog_page_225.pdf pn = 'M20-781{n:02}45' number_of_rows = 2 orientation = 'V' pitch = 2.54 peg_drill_tht = 1.02 mount_drill = 1.8 pad_size = [1.78, 1.02] pincount_range = [2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20] def generate_footprint(pins, configuration): mpn = pn.format(n=pins) pins_per_row = pins # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) print(footprint_name) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Harwin {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') ########################## Dimensions ############################## A = 2.54 * pins B = 2.54 * (pins-1) C = B - 2.54 body_edge={ 'left': -2.54, 'right': 2.54, 'top': -A/2, 'bottom': A/2 } ############################# Pads ################################## # # Mount Pegs # if pins == 2: kicad_mod.append(Pad(at=[0, 0], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) else: kicad_mod.append(Pad(at=[0, -C/2], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[0, C/2], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) for pin in range(pins): for x_pitch in [1.27, -1.27]: kicad_mod.append(Pad(at=[x_pitch, -B/2 + pin*pitch], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill_tht, drill=peg_drill_tht, layers=Pad.LAYERS_NPTH)) # # Add pads # kicad_mod.append(PadArray(start=[-2.91, -B/2], initial=1, pincount=pins, increment=1, y_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(start=[2.91, -B/2], initial=pins+1, pincount=pins, increment=1, y_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_arrow_poly= [ {'x': -2.54, 'y': body_edge['top'] + 1.27 - .4}, {'x': -1.9, 'y': body_edge['top'] + 1.27}, {'x': -2.54, 'y': body_edge['top'] + 1.27 + .4}, ] kicad_mod.append(PolygoneLine(polygone=main_arrow_poly, width=configuration['fab_line_width'], layer="F.Fab")) ######################## SilkS Layer ########################### poly_s_top= [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset'] + .7}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset'] + .7}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_top, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_bot= [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset'] - .7}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset'] - .7}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_bot, width=configuration['silk_line_width'], layer="F.SilkS")) ######################## CrtYd Layer ########################### CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] poly_yd = [ {'x': -3.8 - CrtYd_offset, 'y': body_edge['top'] - CrtYd_offset}, {'x': 3.8 + CrtYd_offset, 'y': body_edge['top'] - CrtYd_offset}, {'x': 3.8 + CrtYd_offset, 'y': body_edge['bottom'] + CrtYd_offset}, {'x': -3.8 - CrtYd_offset, 'y': body_edge['bottom'] + CrtYd_offset}, {'x': -3.8 - CrtYd_offset, 'y': body_edge['top'] - CrtYd_offset} ] kicad_mod.append(PolygoneLine(polygone=poly_yd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### cy1 = body_edge['top'] - configuration['courtyard_offset']['connector'] cy2 = body_edge['bottom'] + configuration['courtyard_offset']['connector'] + 0.2 addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Write to File and 3D ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pincount_range: generate_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Harwin/m20-89xx.py ================================================ #!/usr/bin/env python3 import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields import argparse import yaml from KicadModTree import * series = 'M20-890' series_long = 'Male Horizontal Surface Mount Single Row 2.54mm (0.1 inch) Pitch PCB Connector' manufacturer = 'Harwin' pitch = 2.54 datasheet = 'https://cdn.harwin.com/pdfs/M20-890.pdf' pin_min = 3 pin_max = 20 mpn = 'M20-890{pincount:02g}xx' padsize = [2.5, 1] def roundToBase(value, base): if base == 0: return value return round(value/base) * base def gen_fab_pins(origx, origy, kicad_mod, configuration): poly_f_back = [ {'x': origx+3.8, 'y': origy-0.64/2}, {'x': origx-0.9, 'y': origy-0.64/2}, {'x': origx-0.9, 'y': origy+0.64/2}, {'x': origx+3.8, 'y': origy+0.64/2}, ] poly_f_front = [ {'x': origx+6.3, 'y': origy-0.64/2}, {'x': origx+12.3, 'y': origy-0.64/2}, {'x': origx+12.3, 'y': origy+0.64/2}, {'x': origx+6.3, 'y': origy+0.64/2}, ] kicad_mod.append(PolygoneLine(polygone=poly_f_back, width=configuration['fab_line_width'], layer="F.Fab")) kicad_mod.append(PolygoneLine(polygone=poly_f_front, width=configuration['fab_line_width'], layer="F.Fab")) def gen_silk_pins(origx, origy, kicad_mod, configuration, fill): poly_s_back1 = [ {'x': origx+2.5/2+configuration['silk_pad_clearance']+configuration['silk_line_width'], 'y': origy-0.64/2-configuration['silk_line_width']}, {'x': origx+3.8-configuration['silk_line_width'], 'y': origy-0.64/2-configuration['silk_line_width']}, ] poly_s_back2 = [ {'x': origx+2.5/2+configuration['silk_pad_clearance']+configuration['silk_line_width'], 'y': origy+0.64/2+configuration['silk_line_width']}, {'x': origx+3.8-configuration['silk_line_width'], 'y': origy+0.64/2+configuration['silk_line_width']}, ] poly_s_front = [ {'x': origx+6.3+configuration['silk_line_width'], 'y': origy-0.64/2-configuration['silk_line_width']}, {'x': origx+12.3+configuration['silk_line_width'], 'y': origy-0.64/2-configuration['silk_line_width']}, {'x': origx+12.3+configuration['silk_line_width'], 'y': origy+0.64/2+configuration['silk_line_width']}, {'x': origx+6.3+configuration['silk_line_width'], 'y': origy+0.64/2+configuration['silk_line_width']}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_back1, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine(polygone=poly_s_back2, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine(polygone=poly_s_front, width=configuration['silk_line_width'], layer="F.SilkS")) if fill: kicad_mod.append(Pad(type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[origx+configuration['silk_line_width']+(6.3+12.3)/2, origy], size=[6, 0.64+configuration['silk_line_width']], layers=["F.SilkS"])) def gen_footprint(pinnum, manpart, configuration): orientation_str = configuration['orientation_options']['H'] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series='', mpn=manpart, num_rows=1, pins_per_row=pinnum, mounting_pad="", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace('__','_') print(footprint_name) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{manufacturer} {series}, {mpn}{alt_mpn}, {pins_per_row} Pins per row ({datasheet}), generated with kicad-footprint-generator".format( manufacturer = manufacturer, series = series_long, mpn = manpart, alt_mpn = '', pins_per_row = pinnum, datasheet = datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry='horizontal')) kicad_mod.setAttribute('smd') # Pads kicad_mod.append(PadArray(start=[-6.775+padsize[0]/2, -(pitch*(pinnum-1))/2], initial=1, pincount=pinnum, increment=1, y_spacing=pitch, size=padsize, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT, drill=None)) # Fab for y in range(0, pinnum): gen_fab_pins(-6.775+padsize[0]/2, -(pitch*(pinnum-1))/2+pitch+(y-1)*2.54, kicad_mod, configuration) poly_f_body = [ {'x': -6.775+padsize[0]/2+3.8, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+0.4+2.54}, {'x': -6.775+padsize[0]/2+3.8+0.4, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54}, {'x': -6.775+padsize[0]/2+6.3, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54}, {'x': -6.775+padsize[0]/2+6.3, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+2.54}, {'x': -6.775+padsize[0]/2+3.8, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+2.54}, {'x': -6.775+padsize[0]/2+3.8, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+0.4+2.54}, ] kicad_mod.append(PolygoneLine(polygone=poly_f_body, width=configuration['fab_line_width'], layer="F.Fab")) # SilkS silkslw = configuration['silk_line_width'] s_body = [ {'x': -6.775+padsize[0]/2+3.8-silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54}, {'x': -6.775+padsize[0]/2+6.3+silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54}, {'x': -6.775+padsize[0]/2+6.3+silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+silkslw+2.54}, {'x': -6.775+padsize[0]/2+3.8-silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+silkslw+2.54}, {'x': -6.775+padsize[0]/2+3.8-silkslw, 'y': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54}, ] kicad_mod.append(PolygoneLine(polygone=s_body, width=configuration['silk_line_width'], layer="F.SilkS")) for y in range(0, pinnum): gen_silk_pins(-6.775+padsize[0]/2, -(pitch*(pinnum-1))/2+pitch+(y-1)*2.54, kicad_mod, configuration, y==0) s_pin1 = [ {'x': -6.775+padsize[0]/2-(2.5/2+configuration['silk_pad_clearance']+configuration['silk_line_width']), 'y': -(pitch*(pinnum-1))/2}, {'x': -6.775+padsize[0]/2-(2.5/2+configuration['silk_pad_clearance']+configuration['silk_line_width']), 'y': -(pitch*(pinnum-1))/2-1/2-configuration['silk_line_width']-configuration['silk_pad_clearance']}, {'x': -6.775+padsize[0]/2, 'y': -(pitch*(pinnum-1))/2-1/2-configuration['silk_line_width']-configuration['silk_pad_clearance']}, ] kicad_mod.append(PolygoneLine(polygone=s_pin1, width=configuration['silk_line_width'], layer="F.SilkS")) # CrtYd cy_offset = configuration['courtyard_offset']['connector'] cy_grid = configuration['courtyard_grid'] bounding_box={ 'left': -6.775+padsize[0]/2-2.5/2, 'right': -6.775+padsize[0]/2+12.3, 'top': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54, 'bottom': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+2.54, } cy_top = roundToBase(bounding_box['top'] - cy_offset, cy_grid) cy_bottom = roundToBase(bounding_box['bottom'] + cy_offset, cy_grid) cy_left = roundToBase(bounding_box['left'] - cy_offset, cy_grid) cy_right = roundToBase(bounding_box['right'] + cy_offset, cy_grid) poly_cy = [ {'x': cy_left, 'y': cy_top}, {'x': cy_right, 'y': cy_top}, {'x': cy_right, 'y': cy_bottom}, {'x': cy_left, 'y': cy_bottom}, {'x': cy_left, 'y': cy_top}, ] kicad_mod.append(PolygoneLine(polygone=poly_cy, layer='F.CrtYd', width=configuration['courtyard_line_width'])) # Text Fields body_edge={ 'left': -6.775+padsize[0]/2+3.8, 'right': -6.775+padsize[0]/2+6.3, 'top': -(pitch*(pinnum-1))/2-pitch-2.54/2-silkslw+2.54, 'bottom': -(pitch*(pinnum-1))/2-pitch-2.54/2+2.54*pinnum+silkslw+2.54, } addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy_top, 'bottom':cy_bottom}, fp_name=footprint_name, text_y_inside_position='center', allow_rotation=True) # 3D model model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) # Output output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) def gen_family(configuration): for x in range(pin_min, pin_max+1): gen_footprint(x, mpn.format(pincount=x), configuration) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) gen_family(configuration) ================================================ FILE: scripts/Connector/Connector_Hirose/00-SMD footprint generators can be found in Connector_SMD_single_row_plus_mounting_pad.md ================================================ The following connector footprints are generated in the generic scirpt located in ../Connector_SMD_single_row_plus_mounting_pad/ - DF52 ================================================ FILE: scripts/Connector/Connector_Hirose/conn_ffc_hirose_fh12_smd_side.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from footprint_keepout_area import addRectangularKeepout series = 'FH12' series_long = 'FH12, FFC/FPC connector' manufacturer = 'Hirose' orientation = 'H' number_of_rows = 1 datasheet = 'https://www.hirose.com/product/en/products/FH12/FH12-24S-0.5SH(55)/' conn_category = "FFC-FPC" lib_by_conn_category = True #pins_per_row per row pins_per_row_range = [6,8,10,11,12,13,14,15,16,17,18,19,20,22,24,25,26,28,30,32,33,34,35,36,40,45,50,53] part_code = "FH12-{n:d}S-0.5SH" # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge = 1 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge = 5 rel_pad_y_inside_edge = 3.7 pad_size_x = 0.3 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y = 1.9 body_size_y = 5.6 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x = 1.8 pitch = 0.5 pad_size = [pad_size_x, rel_pad_y_outside_edge - rel_pad_y_inside_edge] mp_size = [1.8, 2.2] def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_no_series_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "-1MP", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 2*rel_body_edge_x pad_y = -rel_pad_y_outside_edge/2 + pad_size[1]/2 mpad_y = rel_pad_y_outside_edge/2 - mp_size[1]/2 mpad_x = A/2 + center_pad_to_mounting_pad_edge + mp_size[0]/2 kicad_mod.append(Pad(number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[mpad_x, mpad_y], size=mp_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[-mpad_x, mpad_y], size=mp_size, layers=Pad.LAYERS_SMT)) # create pads #createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) kicad_mod.append(PadArray(center=[0,pad_y], pincount=pins, x_spacing=pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=pad_size, layers=Pad.LAYERS_SMT)) x1 = -B/2 x2 = x1 + B y2 = mpad_y + mp_size[1]/2 + rel_body_edge_y y1 = y2 - body_size_y body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['top'] = pad_y - pad_size[1]/2 bb_x = mpad_x + mp_size[0]/2 if bb_x > x2: bounding_box['left'] = -bb_x bounding_box['right'] = bb_x main_body_bottom = body_edge['top'] + 4.6 gap_body_hatch = 0.3 gab_body_hatch_depth = 0.6 hatch_reduced_width = 0.2 poly_outline = [ {'x': 0, 'y': body_edge['top']}, {'x': body_edge['left'], 'y': body_edge['top']}, {'x': body_edge['left'], 'y': main_body_bottom}, {'x': body_edge['left'] + gab_body_hatch_depth, 'y': main_body_bottom}, {'x': body_edge['left'] + gab_body_hatch_depth, 'y': main_body_bottom + gap_body_hatch}, {'x': body_edge['left'] + hatch_reduced_width/2, 'y': main_body_bottom + gap_body_hatch}, {'x': body_edge['left'] + hatch_reduced_width/2, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine( polygone=poly_outline, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine( polygone=poly_outline, x_mirror = 0.0000000001, layer='F.Fab', width=configuration['fab_line_width'])) #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint silk_pad_x_left = -A/2 - pad_size[0]/2 - pad_silk_off silk_mp_top = mpad_y - mp_size[1]/2 - pad_silk_off silk_mp_bottom = mpad_y + mp_size[1]/2 + pad_silk_off kicad_mod.append(PolygoneLine( polygone=[ {'x': silk_pad_x_left,'y':y1}, {'x': x1,'y':y1}, {'x': x1,'y':silk_mp_top} ], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ {'x': -silk_pad_x_left,'y':y1}, {'x': x2,'y':y1}, {'x': x2,'y':silk_mp_top} ], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ {'x': x1,'y':silk_mp_bottom}, {'x': x1,'y':y2}, {'x': x2,'y':y2}, {'x': x2,'y':silk_mp_bottom} ], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker kicad_mod.append(Line( start=[silk_pad_x_left, y1], end=[silk_pad_x_left, pad_y - pad_size[1]/2], layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['top'], 'x': -A/2-sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': -A/2}, {'y': body_edge['top'], 'x': -A/2+sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### KEEPOUT ################################# # k_top = pad_y + pad_size[1]/2 + 0.1 # k_size = [A + pad_size[0], 2.37] # addRectangularKeepout(kicad_mod, [0, k_top+k_size[1]/2], k_size) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Hirose/conn_hirose_df11_tht_top.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'DF11' series_long = 'DF11 through hole' manufacturer = 'Hirose' orientation = 'V' number_of_rows = 2 datasheet = 'https://www.hirose.com/product/document?clcode=&productname=&series=DF11&documenttype=Catalog&lang=en&documentid=D31688_en' # pins_per_row per row pins_per_row_range = range(2,17) # Part number # n = number of circuits total part_code = "DF11-{n}DP-2DSA" pitch = 2 drill = 0.85 pad_to_pad_clearance = 0.8 max_annular_ring = 0.4 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins*2) pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_no_series_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 4 # create pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for initial, initial_y in zip([1, 2], [0, pitch]): kicad_mod.append(PadArray(start=[0, initial_y], initial=initial, increment=2, pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) x1 = -(B-A) / 2 y1 = -1.5 x2 = x1 + B y2 = 1.5 + pitch body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() # Fab kicad_mod.append(RectLine( start={'x': x1,'y': y1}, end={'x': x2,'y': y2}, layer='F.Fab', width=configuration['fab_line_width'])) sl=1 pin = [ {'y': body_edge['top'], 'x': -sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': 0}, {'y': body_edge['top'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint kicad_mod.append(RectLine(start={'x':x1,'y':y1},end={'x':x2,'y':y2}, layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker p1_off = configuration['silk_fab_offset'] + 0.3 L = 1.5 pin = [ {'y': body_edge['top'] + L, 'x': body_edge['left'] - p1_off}, {'y': body_edge['top'] - p1_off, 'x': body_edge['left'] - p1_off}, {'y': body_edge['top'] - p1_off, 'x': body_edge['left'] + L} ] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) #side-wall thickness S S = 0.4 #bottom line kicad_mod.append(PolygoneLine( polygone=[ {'x':x1,'y':2}, {'x':x1+S,'y':2}, {'x':x1+S,'y':y2-S}, {'x':x2-S,'y':y2-S}, {'x':x2-S,'y':2}, {'x':x2,'y':2}], layer='F.SilkS', width=configuration['silk_line_width'])) #left mark kicad_mod.append(PolygoneLine( polygone=[ {'x':x1,'y':1}, {'x':x1+S,'y':1}, {'x':x1+S,'y':y1+S}, {'x':0.5,'y':y1+S}, {'x':0.5,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) #right mark kicad_mod.append(PolygoneLine( polygone=[ {'x':x2,'y':1}, {'x':x2-S,'y':1}, {'x':x2-S,'y':y1+S}, {'x':x2-2.5-off,'y':y1+S}, {'x':x2-2.5-off,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) #middle line if pins > 2: kicad_mod.append(PolygoneLine( polygone=[ {'x':1.5,'y':y1}, {'x':1.5,'y':y1+S}, {'x':x2-3.5-off,'y':y1+S}, {'x':x2-3.5-off,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Hirose/conn_hirose_df12c_ds_smd_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'DF12' series_long = 'DF12C SMD' manufacturer = 'Hirose' orientation = 'V' number_of_rows = 2 datasheet = 'https://www.hirose.com/product/document?clcode=CL0537-0694-9-81&productname=DF12C(3.0)-50DS-0.5V(81)&series=DF12&documenttype=2DDrawing&lang=en&documentid=0000994748' #Hirose part number part_code = "DF12C3.0-{n:02}DS-0.5V" pitch = 0.5 pad_size = [0.3, 1.6] pad_size_paste = [0.28,1.2] pins_per_row_range = [10,20,30,40,50,60,14,32,36] def generate_one_footprint(idx, pins, configuration): mpn = part_code.format(n=pins) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=int(pins/2), mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) ########################## Dimensions ############################## if(idx == 6): #14 Pins A = 5.6 B = 3.0 elif (idx == 7): #32 Pins A = 10.1 B = 7.5 elif (idx == 8): #36 Pins A = 11.1 B = 8.5 else: A = 4.6 + (idx * 2.5) B = A - 2.6 body_edge_out={ 'left': round(-A/2 ,2), 'right': round(A/2 ,2), 'top': -1.8, 'bottom': 1.8 } D = A - 1.5 body_edge_in={ 'left': round(-D/2 ,2), 'right': round(D/2 ,2), 'top': -1.2, 'bottom': 1.2 } ############################# Pads ################################## # # Add pads # #Pad only with F.Cu and F.Mask CPins=int(pins / 2) kicad_mod.append(PadArray(start=[-B/2, -1.8], initial=1, pincount=CPins, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Cu", "F.Mask"])) kicad_mod.append(PadArray(start=[-B/2, 1.8], initial=CPins + 1, pincount=CPins, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Cu", "F.Mask"])) #F.Paste kicad_mod.append(PadArray(start=[-B/2, -2], initial='', increment=0, pincount=CPins, x_spacing=pitch, size=pad_size_paste, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Paste"])) kicad_mod.append(PadArray(start=[-B/2, 2], initial='', increment=0, pincount=CPins, x_spacing=pitch, size=pad_size_paste, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Paste"])) ######################## Fabrication Layer ########################### main_body_out_poly= [ {'x': body_edge_out['left'], 'y': body_edge_out['bottom']}, {'x': body_edge_out['left'], 'y': body_edge_out['top']}, {'x': body_edge_out['right'], 'y': body_edge_out['top']}, {'x': body_edge_out['right'], 'y': body_edge_out['bottom']}, {'x': body_edge_out['left'], 'y': body_edge_out['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_body_out_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_body_in_poly= [ {'x': body_edge_in['left'], 'y': body_edge_in['bottom']}, {'x': body_edge_in['left'], 'y': body_edge_in['top']}, {'x': body_edge_in['right'], 'y': body_edge_in['top']}, {'x': body_edge_in['right'], 'y': body_edge_in['bottom']}, {'x': body_edge_in['left'], 'y': body_edge_in['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_body_in_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_arrow_poly= [ {'x': (-B/2)-0.2, 'y': body_edge_out['top'] - 0.75}, {'x': -B/2, 'y': -1.8}, {'x': (-B/2)+0.2, 'y': body_edge_out['top'] - 0.75}, {'x': (-B/2)-0.2, 'y': body_edge_out['top'] - 0.75} ] kicad_mod.append(PolygoneLine(polygone=main_arrow_poly, width=configuration['fab_line_width'], layer="F.Fab")) ######################## SilkS Layer ########################### offset = (pad_size[0]/2)+0.2+.06 poly_left= [ {'x': -(B/2) - offset, 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': -(A/2) - configuration['silk_fab_offset'], 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge_out['left'] - configuration['silk_fab_offset'], 'y': body_edge_out['top'] - configuration['silk_fab_offset']}, {'x': -(B/2) - offset, 'y': body_edge_out['top'] - configuration['silk_fab_offset']}, {'x': -(B/2) - offset, 'y': body_edge_out['top'] - (pad_size[1]/3)} ] kicad_mod.append(PolygoneLine(polygone=poly_left, width=configuration['silk_line_width'], layer="F.SilkS")) poly_right= [ {'x': (B/2) + offset, 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': (A/2) + configuration['silk_fab_offset'], 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge_out['right'] + configuration['silk_fab_offset'], 'y': body_edge_out['top'] - configuration['silk_fab_offset']}, {'x': (B/2) + offset, 'y': body_edge_out['top'] - configuration['silk_fab_offset']} ] kicad_mod.append(PolygoneLine(polygone=poly_right, width=configuration['silk_line_width'], layer="F.SilkS")) ######################## CrtYd Layer ########################### CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] poly_yd = [ {'x': roundToBase(body_edge_out['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(-2.6 - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(2.6 + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(2.6 + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(-2.6 - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(-2.6 - CrtYd_offset, CrtYd_grid)} ] kicad_mod.append(PolygoneLine(polygone=poly_yd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### cy1 = roundToBase(body_edge_out['top'] -1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(body_edge_out['bottom'] + 1 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge_out, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Write to File and 3D ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) idx = 0 for pincount in pins_per_row_range: generate_one_footprint(idx, pincount, configuration) idx += 1 ================================================ FILE: scripts/Connector/Connector_Hirose/conn_hirose_df12e_dp_smd_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'DF12' series_long = 'DF12E SMD' manufacturer = 'Hirose' orientation = 'V' number_of_rows = 2 datasheet = 'https://www.hirose.com/product/document?clcode=CL0537-0834-6-81&productname=DF12E(3.0)-50DP-0.5V(81)&series=DF12&documenttype=2DDrawing&lang=en&documentid=0000992393' #Hirose part number part_code = "DF12E3.0-{n:02}DP-0.5V" pitch = 0.5 pad_size = [0.3, 1.6] pad_size_paste = [0.28,1.2] pins_per_row_range = [10,20,30,40,50,60,80,14,32,36] def generate_one_footprint(idx, pins, configuration): mpn = part_code.format(n=pins) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=int(pins/2), mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) ########################## Dimensions ############################## if(idx == 6): #80 Pins A = 22.2 B = 19.5 elif(idx == 7): #14 Pins A = 5.7 B = 3.0 elif (idx == 8): #32 Pins A = 10.2 B = 7.5 elif (idx == 9): #36 Pins A = 11.2 B = 8.5 else: A = 4.7 + (idx * 2.5) B = A - 2.7 body_edge_out={ 'left': round(-A/2 ,2), 'right': round(A/2 ,2), 'top': -1.9, 'bottom': 1.9 } D = A - 1.5 body_edge_in={ 'left': round(-D/2 ,2), 'right': round(D/2 ,2), 'top': -1.225, 'bottom': 1.225 } ############################# Pads ################################## # # Add pads # #Pad only with F.Cu and F.Mask CPins=int(pins / 2) kicad_mod.append(PadArray(start=[-B/2, 1.8], initial=1, pincount=CPins, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Cu", "F.Mask"])) kicad_mod.append(PadArray(start=[-B/2, -1.8], initial=CPins + 1, pincount=CPins, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Cu", "F.Mask"])) #F.Paste kicad_mod.append(PadArray(start=[-B/2, 2], initial='', increment=0, pincount=CPins, x_spacing=pitch, size=pad_size_paste, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Paste"])) kicad_mod.append(PadArray(start=[-B/2, -2], initial='', increment=0, pincount=CPins, x_spacing=pitch, size=pad_size_paste, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=["F.Paste"])) ######################## Fabrication Layer ########################### main_body_out_poly= [ {'x': body_edge_out['left'], 'y': body_edge_out['bottom']}, {'x': body_edge_out['left'], 'y': body_edge_out['top']}, {'x': body_edge_out['right'], 'y': body_edge_out['top']}, {'x': body_edge_out['right'], 'y': body_edge_out['bottom']}, {'x': body_edge_out['left'], 'y': body_edge_out['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_body_out_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_body_in_poly= [ {'x': body_edge_in['left'], 'y': body_edge_in['bottom']}, {'x': body_edge_in['left'], 'y': body_edge_in['top']}, {'x': body_edge_in['right'], 'y': body_edge_in['top']}, {'x': body_edge_in['right'], 'y': body_edge_in['bottom']}, {'x': body_edge_in['left'], 'y': body_edge_in['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_body_in_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_arrow_poly= [ {'x': (-B/2)-0.2, 'y': body_edge_out['bottom'] + 0.75}, {'x': -B/2, 'y': 1.8}, {'x': (-B/2)+0.2, 'y': body_edge_out['bottom'] + 0.75}, {'x': (-B/2)-0.2, 'y': body_edge_out['bottom'] + 0.75} ] kicad_mod.append(PolygoneLine(polygone=main_arrow_poly, width=configuration['fab_line_width'], layer="F.Fab")) ######################## SilkS Layer ########################### offset = (pad_size[0]/2)+0.2+.06 poly_left= [ {'x': -(B/2) - offset, 'y': body_edge_out['bottom'] + (pad_size[1]/3)}, {'x': -(B/2) - offset, 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': -(A/2) - configuration['silk_fab_offset'], 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge_out['left'] - configuration['silk_fab_offset'], 'y': body_edge_out['top'] - configuration['silk_fab_offset']}, {'x': -(B/2) - offset, 'y': body_edge_out['top'] - configuration['silk_fab_offset']} ] kicad_mod.append(PolygoneLine(polygone=poly_left, width=configuration['silk_line_width'], layer="F.SilkS")) poly_right= [ {'x': (B/2) + offset, 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': (A/2) + configuration['silk_fab_offset'], 'y': body_edge_out['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge_out['right'] + configuration['silk_fab_offset'], 'y': body_edge_out['top'] - configuration['silk_fab_offset']}, {'x': (B/2) + offset, 'y': body_edge_out['top'] - configuration['silk_fab_offset']} ] kicad_mod.append(PolygoneLine(polygone=poly_right, width=configuration['silk_line_width'], layer="F.SilkS")) ######################## CrtYd Layer ########################### CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] poly_yd = [ {'x': roundToBase(body_edge_out['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(-2.6 - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(2.6 + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(2.6 + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(-2.6 - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge_out['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(-2.6 - CrtYd_offset, CrtYd_grid)} ] kicad_mod.append(PolygoneLine(polygone=poly_yd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### cy1 = roundToBase(body_edge_out['top'] -1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(body_edge_out['bottom'] + 1 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge_out, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Write to File and 3D ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) idx = 0 for pincount in pins_per_row_range: generate_one_footprint(idx, pincount, configuration) idx += 1 ================================================ FILE: scripts/Connector/Connector_Hirose/conn_hirose_df13_tht_side.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'DF13' series_long = 'DF13 through hole' manufacturer = 'Hirose' orientation = 'H' number_of_rows = 1 datasheet = 'https://www.hirose.com/product/en/products/DF13/DF13-4P-1.25DS%2820%29/' #pins_per_row per row pins_per_row_range = [2,3,4,5,6,7,8,9,10,11,12,14,15] #Molex part number #n = number of circuits per row part_code = "DF13-{n:02}P-1.25DS" pitch = 1.25 drill = 0.6 pad_to_pad_clearance = 0.8 max_annular_ring = 0.4 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_no_series_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # create pads #createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[0,0], pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) A = (pins - 1) * pitch B = A + 2.9 x1 = -(B-A) / 2 y1 = -4.5 x2 = x1 + B y2 = y1 + 5.4 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() #draw the connector outline on the F.Fab layer kicad_mod.append(RectLine( start={'x': x1,'y': y1}, end={'x': x2,'y': y2}, layer='F.Fab', width=configuration['fab_line_width'])) #line offset off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #y offset from pins 'q' q = -0.3 #x offset from border w w = 0.55 #outline size o o = 0.15 #draw the main outline around the footprint kicad_mod.append(PolygoneLine( polygone=[ {'x':-0.2*pitch,'y':pad_size[1]/2+pad_silk_off}, {'x':-0.2*pitch,'y':y2}, {'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':(pins -1 + 0.2) * pitch,'y':y2}, {'x':(pins -1 + 0.2) * pitch,'y':pad_size[1]/2+pad_silk_off}], layer='F.SilkS', width=configuration['silk_line_width'])) #line across the middle py = -2.5 kicad_mod.append(Line(start={'x':x1+w,'y':py},end={'x':x2-w,'y':py}, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start={'x':x1+w,'y':py+1.5},end={'x':x2-w,'y':py+1.5}, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start={'x':x1+w,'y':y1},end={'x':x1+w,'y':y2}, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start={'x':x2-w,'y':y1},end={'x':x2-w,'y':y2}, layer='F.SilkS', width=configuration['silk_line_width'])) #add picture of pins #add pictures of pins #pin-width w #pin-length l w = 0.15 l = 1.5 for p in range(pins): px = p * pitch kicad_mod.append(PolygoneLine( polygone=[ {'x': px-w,'y': py}, {'x': px-w,'y': py-l+0.25*w}, {'x': px,'y': py-l}, {'x': px+w,'y': py-l+0.25*w}, {'x': px+w,'y': py}], layer='F.SilkS', width=configuration['silk_line_width'])) #add outline around pins if p > 0: kicad_mod.append(PolygoneLine( polygone=[ {'x':px-0.8*pitch,'y':pad_size[1]/2+pad_silk_off}, {'x':px-0.8*pitch,'y':y2}, {'x':px-0.2*pitch,'y':y2}, {'x':px-0.2*pitch,'y':pad_size[1]/2+pad_silk_off}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker xm = 0 ym = 1.5 m = 0.3 kicad_mod.append(PolygoneLine( polygone=[ {'x':xm,'y':ym}, {'x':xm - m,'y':ym + 2 * m}, {'x':xm + m,'y':ym + 2 * m}, {'x':xm,'y':ym}], layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['bottom'], 'x': -sl/2}, {'y': body_edge['bottom'] - sl/sqrt(2), 'x': 0}, {'y': body_edge['bottom'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Hirose/conn_hirose_df13_tht_top.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'DF13' series_long = 'DF13 through hole' manufacturer = 'Hirose' orientation = 'V' number_of_rows = 1 datasheet = 'https://www.hirose.com/product/en/products/DF13/DF13-2P-1.25DSA%2850%29/' #pins_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row part_code = "DF13-{n:02}P-1.25DSA" pitch = 1.25 drill = 0.6 pad_to_pad_clearance = 0.8 max_annular_ring = 0.4 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_no_series_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 2.9 # create pads #createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[0,0], pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) x1 = -(B-A) / 2 y1 = -2.2 x2 = x1 + B y2 = 1.2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() kicad_mod.append(RectLine( start={'x': x1,'y': y1}, end={'x': x2,'y': y2}, layer='F.Fab', width=configuration['fab_line_width'])) #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint kicad_mod.append(RectLine(start={'x':x1,'y':y1},end={'x':x2,'y':y2}, layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker p1_off = configuration['silk_fab_offset'] + 0.3 L = 1.5 pin = [ {'y': body_edge['bottom'] - L, 'x': body_edge['left'] - p1_off}, {'y': body_edge['bottom'] + p1_off, 'x': body_edge['left'] - p1_off}, {'y': body_edge['bottom'] + p1_off, 'x': body_edge['left'] + L} ] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['bottom'], 'x': -sl/2}, {'y': body_edge['bottom'] - sl/sqrt(2), 'x': 0}, {'y': body_edge['bottom'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) #side-wall thickness S S = 0.3 #bottom line kicad_mod.append(PolygoneLine( polygone=[ {'x':x1,'y':0}, {'x':x1+S,'y':0}, {'x':x1+S,'y':y2-S}, {'x':x2-S,'y':y2-S}, {'x':x2-S,'y':0}, {'x':x2,'y':0}], layer='F.SilkS', width=configuration['silk_line_width'])) #left mark #gap g g = 0.75 kicad_mod.append(PolygoneLine( polygone=[ {'x':x1,'y':-g}, {'x':x1+S,'y':-g}, {'x':x1+S,'y':y1+S*1.5}, {'x':x1+2*S,'y':y1+S*1.5}, {'x':x1+2*S,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ {'x':x2,'y':-g}, {'x':x2-S,'y':-g}, {'x':x2-S,'y':y1+S*1.5}, {'x':x2-2*S,'y':y1+S*1.5}, {'x':x2-2*S,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) #middle line if pins == 2: polygone=[{'x':x1+2*S,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+1.5*S}, {'x':x2-2*S,'y':y1+1.5*S}] else: polygone=[ {'x':x1+2*S,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+1.5*S}, {'x':A-0.8*pitch,'y':y1+1.5*S}, {'x':A-0.8*pitch,'y':y1+0.5*S}, {'x':A-0.2*pitch,'y':y1+0.5*S}, {'x':A-0.2*pitch,'y':y1+1.5*S}, {'x':x2-2*S,'y':y1+1.5*S}] kicad_mod.append(PolygoneLine(polygone=polygone, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Hirose/conn_hirose_df13c_smd_top.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from footprint_keepout_area import addRectangularKeepout series = 'DF13C' series_long = 'DF13C SMD' manufacturer = 'Hirose' orientation = 'V' number_of_rows = 1 datasheet = 'https://www.hirose.com/product/en/products/DF13/DF13C-10P-1.25V%2851%29/' #pins_per_row per row pins_per_row_range = [2,3,4,5,6,7,8,9,10,11,12,14,15] mpn_param_1 = ['2','5','8','0','3','6','9','1','4','3','6','1','4'] part_code = "CL535-04{n:02d}-{param_1:s}-51" # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge = 1.45 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge = 4.7 rel_pad_y_inside_edge = 2.9 pad_size_x = 0.7 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y = 0.6 body_size_y = 3.4 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x = 2.2 pitch = 1.25 pad_size = [pad_size_x, rel_pad_y_outside_edge - rel_pad_y_inside_edge] mp_size = [1.6, 2.2] def generate_one_footprint(idx, pins, configuration): mpn = part_code.format(n=pins, param_1=mpn_param_1[idx]) pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "-1MP", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 2*rel_body_edge_x pad_y = -rel_pad_y_outside_edge/2 + pad_size[1]/2 mpad_y = rel_pad_y_outside_edge/2 - mp_size[1]/2 mpad_x = A/2 + center_pad_to_mounting_pad_edge + mp_size[0]/2 kicad_mod.append(Pad(number = configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[mpad_x, mpad_y], size=mp_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number = configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[-mpad_x, mpad_y], size=mp_size, layers=Pad.LAYERS_SMT)) # create pads #createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) kicad_mod.append(PadArray(center=[0,pad_y], pincount=pins, x_spacing=pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=pad_size, layers=Pad.LAYERS_SMT)) x1 = -B/2 x2 = x1 + B y2 = mpad_y + mp_size[1]/2 + rel_body_edge_y y1 = y2 - body_size_y body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['top'] = pad_y - pad_size[1]/2 bb_x = mpad_x + mp_size[0]/2 if bb_x > x2: bounding_box['left'] = -bb_x bounding_box['right'] = bb_x kicad_mod.append(RectLine( start={'x': x1,'y': y1}, end={'x': x2,'y': y2}, layer='F.Fab', width=configuration['fab_line_width'])) #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint silk_pad_x_left = -A/2 - pad_size[0]/2 - pad_silk_off silk_mp_top = mpad_y - mp_size[1]/2 - pad_silk_off silk_mp_bottom = mpad_y + mp_size[1]/2 + pad_silk_off kicad_mod.append(PolygoneLine( polygone=[ {'x': silk_pad_x_left,'y':y1}, {'x': x1,'y':y1}, {'x': x1,'y':silk_mp_top} ], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ {'x': -silk_pad_x_left,'y':y1}, {'x': x2,'y':y1}, {'x': x2,'y':silk_mp_top} ], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ {'x': x1,'y':silk_mp_bottom}, {'x': x1,'y':y2}, {'x': x2,'y':y2}, {'x': x2,'y':silk_mp_bottom} ], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker kicad_mod.append(Line( start=[silk_pad_x_left, y1], end=[silk_pad_x_left, pad_y - pad_size[1]/2], layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['top'], 'x': -A/2-sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': -A/2}, {'y': body_edge['top'], 'x': -A/2+sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### KEEPOUT ################################# k_top = pad_y + pad_size[1]/2 + 0.1 k_size = [A + pad_size[0], 2.37] addRectangularKeepout(kicad_mod, [0, k_top+k_size[1]/2], k_size) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) idx = 0 for pins_per_row in pins_per_row_range: generate_one_footprint(idx, pins_per_row, configuration) idx += 1 ================================================ FILE: scripts/Connector/Connector_Hirose/conn_hirose_df63_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' """ footprint specific details to go here Hirose DF63 URL: https://www.hirose.com/product/en/products/DF63/ Datasheet: https://www.hirose.com/product/document?clcode=&productname=&series=DF63&documenttype=Catalog&lang=en&documentid=D31622_en """ import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'DF63' series_long = 'DF63 through hole' manufacturer = 'Hirose' orientation = 'V' number_of_rows = 1 datasheet = 'https://www.hirose.com/product/en/products/DF63/' #pins_per_row per row pins_per_row_range = [1,2,3,4,5,6] types = ['M', 'R'] #Hirose part number #n = number of circuits per row part_code = "DF63{f:s}-{n:d}P-3.96DSA" pitch = 3.96 drill = 1.8 mount_size = 1.6 pad_to_pad_clearance = 1.5 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, form_type, configuration): mpn = part_code.format(n=pins, f=form_type) off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_no_series_format_string'].format(man=manufacturer, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{:s} {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(manufacturer, series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #vertical center of connector y2 = 3.25 + mount_size / 2 y1 = y2 - 7.05 yt = y2 - 8 #Major dimensions B = ( pins - 1 ) * pitch A = B + 4.7 if pins == 1: A = 6.2 #calculate major dimensions x1 = (B - A) / 2 x2 = x1 + A body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['top'] = yt #pins optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append( PadArray( pincount=pins, initial = 1, start = [0, 0], x_spacing = pitch, type = Pad.TYPE_THT, layers = Pad.LAYERS_THT, shape = pad_shape, size = pad_size, drill = drill, **optional_pad_params ) ) #mounting hole if form_type in ['M', '']: peg_location = [-1.5, 3.25] else: peg_location = [B+1.5, 3.25] kicad_mod.append(Pad(at=peg_location,type=Pad.TYPE_NPTH,layers=Pad.LAYERS_NPTH,shape=Pad.SHAPE_CIRCLE,size=mount_size,drill=mount_size)) #connector outline #tab thickness t = 1.2 def outline(offset=0): outline = [ {'x': B/2, 'y': y2 + offset}, {'x': x1 - offset, 'y': y2 + offset}, {'x': x1 - offset, 'y': yt - offset}, {'x': x1 + t + offset, 'y': yt - offset}, {'x': x1 + t + offset, 'y': y1 - offset}, {'x': B/2, 'y': y1 - offset}, ] return outline kicad_mod.append(PolygoneLine(polygone=outline(),layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(),x_mirror=B/2, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(offset=off), layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(offset=off),x_mirror=B/2, layer='F.SilkS', width=configuration['silk_line_width'])) #draw lines between pads on F.Fab for i in range(pins - 1): x = (i + 0.5) * pitch kicad_mod.append(Line(start=[x,y1], end=[x,y2], layer='F.Fab', width=configuration['fab_line_width'])) #pin-1 indicator kicad_mod.append(Circle(center=[0,-3.75], radius=0.25, layer='F.SilkS', width=configuration['silk_line_width'])) sl=2 pin = [ {'y': body_edge['top'], 'x': -sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': 0}, {'y': body_edge['top'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=-3.75) ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: for form_type in types: if form_type is 'R' and pins_per_row is 6: continue if form_type is 'M' and pins_per_row in [5,6]: form_type = '' generate_one_footprint(pins_per_row, form_type, configuration) ================================================ FILE: scripts/Connector/Connector_Hirose/helpers.py ================================================ def roundToBase(value, base): if base == 0: return value return round(value/base) * base ================================================ FILE: scripts/Connector/Connector_Hirose/not_in_official_lib/df33_straight_pth.py ================================================ #!/usr/bin/env python3 import sys import os sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) from kicad_mod import KicadMod, createNumberedPadsTHT # http://www.jst-mfg.com/product/pdf/eng/ePH.pdf pitch = 3.3 manu = "Hirose" suffix = "Straight" desc = "Hirose DF33 series connector, 3.30mm pitch, top entry PTH" tags = "connector hirose df33 top straight vertical through thru hole" for pincount in range(2,16): part = "DF33C-{pincount:02}P-125DSA".format(pincount=pincount) footprint_name = "{0}_{1}_{2:02}x{3:.2f}mm_{4}".format(manu,part,pincount,pitch,suffix) kicad_mod = KicadMod(footprint_name) kicad_mod.setDescription(desc) kicad_mod.setTags(tags) # set general values kicad_mod.addText('reference', 'REF**', {'x':0, 'y':2.5}, 'F.SilkS') kicad_mod.addText('value', footprint_name, {'x':0, 'y':4}, 'F.Fab') drill = 0.6 x_dia = 0.95 y_dia = 1.25 # create pads createNumberedPadsTHT(kicad_mod, pincount, pitch, drill, {'x':x_dia, 'y':y_dia}) A = (pincount - 1) * pitch B = A + 2.9 x1 = -(B-A) / 2 y1 = -2.2 x2 = x1 + B y2 = 1.2 #line offset off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint kicad_mod.addRectLine({'x':x1,'y':y1},{'x':x2,'y':y2}) #add pin-1 marker xm = 0 ym = -2.8 m = 0.3 kicad_mod.addPolygoneLine([{'x':xm,'y':ym}, {'x':xm - m,'y':ym - 2 * m}, {'x':xm + m,'y':ym - 2 * m}, {'x':xm,'y':ym}]) #side-wall thickness S S = 0.5 #bottom line kicad_mod.addPolygoneLine([{'x':x1,'y':0}, {'x':x1+S,'y':0}, {'x':x1+S,'y':y2-S}, {'x':x2-S,'y':y2-S}, {'x':x2-S,'y':0}, {'x':x2,'y':0}]) #left mark #gap g g = 0.75 kicad_mod.addPolygoneLine([{'x':x1,'y':-g}, {'x':x1+S,'y':-g}, {'x':x1+S,'y':y1+S*1.5}, {'x':x1+2*S,'y':y1+S*1.5}, {'x':x1+2*S,'y':y1}]) kicad_mod.addPolygoneLine([{'x':x2,'y':-g}, {'x':x2-S,'y':-g}, {'x':x2-S,'y':y1+S*1.5}, {'x':x2-2*S,'y':y1+S*1.5}, {'x':x2-2*S,'y':y1}]) #middle line kicad_mod.addPolygoneLine([{'x':x1+2*S,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+1.5*S}, {'x':0.2*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+0.5*S}, {'x':0.8*pitch,'y':y1+1.5*S}, {'x':A-0.8*pitch,'y':y1+1.5*S}, {'x':A-0.8*pitch,'y':y1+0.5*S}, {'x':A-0.2*pitch,'y':y1+0.5*S}, {'x':A-0.2*pitch,'y':y1+1.5*S}, {'x':x2-2*S,'y':y1+1.5*S}]) """ #add pictures of pins #pin-width w #pin-length l w = 0.32 l = 3.5 py = -2.5 kicad_mod.addLine({'x':x1+T,'y':py},{'x':x2-T,'y':py}) kicad_mod.addLine({'x':x1+T,'y':py+1},{'x':x2-T,'y':py+1}) for p in range(pincount): px = p * pitch kicad_mod.addPolygoneLine([{'x': px,'y': py}, {'x': px-w,'y': py}, {'x': px-w,'y': py-l+0.25*w}, {'x': px,'y': py-l}, {'x': px+w,'y': py-l+0.25*w}, {'x': px+w,'y': py}, {'x': px,'y': py}]) """ #add a courtyard cy = 0.5 kicad_mod.addRectLine({'x':x1-cy,'y':y1-cy},{'x':x2+cy,'y':y2+cy},"F.CrtYd",0.05) kicad_mod.model = "Connectors_Hirose.3dshapes/" + footprint_name + ".wrl" #shift the model along if pincount % 2 == 0: #even xOff = (pincount / 2 - 0.5) * pitch else: xOff = (pincount / 2) * pitch kicad_mod.model_pos['x'] = xOff / 25.4 kicad_mod.model_rot['z'] = 180 # output kicad model f = open(footprint_name + ".kicad_mod","w") f.write(kicad_mod.__str__()) f.close() ================================================ FILE: scripts/Connector/Connector_Hirose/not_in_official_lib/df63_angled.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append("..\\..") from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray """ footprint specific details to go here Hirose DF63 URL: https://www.hirose.com/product/en/products/DF63/ Datasheet: https://www.hirose.com/product/en/download_file/key_name/DF63/category/Catalog/doc_file_id/51104/?file_category_id=4&item_id=47&is_series=1 """ manu = "Hirose" series = "DF63" pitch = 3.96 drill = 1.8 pad_size = 3 mount_size = 1.6 #vertical center of connector y2 = 3.25 + mount_size / 2 y1 = y2 - 7.05 yt = y2 - 8 desc = "{manu} {series} connector, {code}, {p}mm pitch, side entry THT" tags = "connector hirose df63 horizontal through hole" pins = [2,3] for pincount in pins: part = "DF63-{pincount}P-3.96DS".format(series=series,pincount=pincount) footprint_name = "{manu}_{pn}_{n:02}x{pitch:.2f}mm_Angled".format( manu = manu, pn = part, n = pincount, pitch = pitch ) print(footprint_name) fp = Footprint(footprint_name) #description fp.setDescription(desc.format(manu=manu, series=series, p=pitch, code=part)) fp.setTags(tags) # text fp.append(Text(type='reference', text='REF**', at=[0, -5.2], layer='F.SilkS')) fp.append(Text(type='value', text=footprint_name, at=[0,5.4 ], layer='F.Fab')) #Major dimensions B = ( pincount - 1 ) * pitch A = B + 4.7 #pins fp.append( PadArray( pincount=pincount, initial = 1, start = [0, 0], x_spacing = pitch, type = Pad.TYPE_THT, layers = Pad.LAYERS_THT, shape = Pad.SHAPE_CIRCLE, size = pad_size, drill = drill, ) ) #calculate major dimensions x1 = (B - A) / 2 x2 = x1 + A #courtyard fp.append(RectLine(start=[x1,yt],end=[x2,y2],layer='F.CrtYd',width=0.05,grid=0.05,offset=0.5)) #mounting hole if pincount > 1: fp.append(Pad(at=[-1.5,3.25],type=Pad.TYPE_NPTH,layers=Pad.LAYERS_NPTH,shape=Pad.SHAPE_CIRCLE,size=mount_size,drill=mount_size)) #connector outline #tab thickness t = 1.2 def outline(offset=0): outline = [ {'x': B/2, 'y': y2 + offset}, {'x': x1 - offset, 'y': y2 + offset}, {'x': x1 - offset, 'y': yt - offset}, {'x': x1 + t + offset, 'y': yt - offset}, {'x': x1 + t + offset, 'y': y1 - offset}, {'x': B/2, 'y': y1 - offset}, ] return outline fp.append(PolygoneLine(polygone=outline(),layer='F.Fab')) fp.append(PolygoneLine(polygone=outline(),layer='F.Fab',x_mirror=B/2)) fp.append(PolygoneLine(polygone=outline(offset=0.15))) fp.append(PolygoneLine(polygone=outline(offset=0.15),x_mirror=B/2)) #draw lines between pads on F.Fab for i in range(pincount - 1): x = (i + 0.5) * pitch fp.append(Line(start=[x,y1],end=[x,y2],layer='F.Fab')) """ #connector outline (f.fab layer) #y-top yt = yp - ph / 2 + 0.3 #y-bottom yb = yt + 2.77 #y-notch yn = 0.5 outline = [ {'x': 0,'y': yt}, {'x': -B/2 - pitch,'y': yt}, {'x': -B/2 - pitch,'y': yt}, {'x': -B/2 - pitch,'y': yt + yn}, {'x': -A/2,'y': yt + yn}, {'x': -A/2,'y': yb}, {'x': 0,'y': yb}, ] fp.append(PolygoneLine(polygone=outline,layer='F.Fab')) fp.append(PolygoneLine(polygone=outline,layer='F.Fab',x_mirror=0)) #draw pin-1 indicator on F.Fab #size of arrow a a = 0.6 fp.append(PolygoneLine(polygone=[ {'x': -B/2, 'y': yt + a}, {'x': -B/2 - a/2, 'y': yt}, {'x': -B/2 + a/2, 'y': yt}, {'x': -B/2, 'y': yt + a}], layer='F.Fab')) #draw pin-1 indicator on Silk.S ya = -2 fp.append(PolygoneLine(polygone=[ {'x': -B/2, 'y': ya}, {'x': -B/2 - a/2, 'y': ya - a}, {'x': -B/2 + a/2, 'y': ya - a}, {'x': -B/2, 'y': ya}, ])) #silkscreen #offset from pads op = 0.3 #offset from F.fab of = 0.15 #Sides silk = [ {'x': -B/2 - pw/2 - op, 'y': yt - of}, {'x': -B/2 - of - pitch, 'y': yt - of}, {'x': -B/2 - of - pitch, 'y': yt - of + yn}, {'x': -A/2 - of, 'y': yt - of + yn}, {'x': -A/2 - of, 'y': ym - mh / 2 - op}, ] fp.append(PolygoneLine(polygone = silk)) fp.append(PolygoneLine(polygone = silk, x_mirror = 0)) #bottom line fp.append(Line( start=[-xm + mw/2 + op, yb + of], end =[ xm - mw/2 - op, yb + of])) #courtyard y1 = yp - ph / 2 y2 = ym + mh / 2 x1 = xm + mw / 2 fp.append(RectLine(start=[-x1,y1],end=[x1,y2],layer='F.CrtYd',width=0.05,grid=0.05,offset=0.5)) """ #add a 3D model reference fp.append(Model(filename="Connectors_Hirose.3dshapes/" + footprint_name + ".wrl")) #filename filename = output_dir + footprint_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) ================================================ FILE: scripts/Connector/Connector_IEC_DIN/generate_din41612.py ================================================ #!/usr/bin/env python3 import sys import os import math sys.path.append(os.path.join(sys.path[0],"..","..","..")) # for KicadModTree sys.path.append(os.path.join(sys.path[0],"..","..","tools")) # for drawing_tools from KicadModTree import * from drawing_tools import * # According to IEC 60603-2 §3 and DIN 41612-1 §2 connector names should be like # this: # "${STANDARD}${TYPE}${PINCOUNT}${GENDER}${METHOD}-${FURTHER_INFO}" # with: # STANDARD: either "IEC 60603-2 " or "DIN 41 612-" # TYPE: B, C, D, E, F, G, H, M, Q, R, S, T, U, V, W # PINCOUNT: Number of populated pins, 3 digits # SEX: M: male, F: female # METHOD: A: screws, C (DIN) crimp (IEC), D: insulation displacement (IEC), # K: clamps (DIN), P: press fit (DIN) S: solder, T: blade receptacle, # W: wire wrap # FURTHER_INFO: Pin length, materials and other things that don't change the # footprint. # # This library choose to use the prefix "Conn_DIN41612_", because Din 41612 is # more common term. # METHOD and further are ommited, because the footprint is suited for # soldering and press fit. # # It includes half and third sized connectors, that are not part of IEC 60603 # or DIN 41612. These connectors are named 2X and 3X, a convention also used by # Harting. # When a manufacturer is mentioned in the comment, it means that # the value is explicitly stated in a datasheet by this company. ROW_IDENTIFIER = ('a', 'b') LIBRARY_NAME = 'Connector_DIN' ORIENTATION = {'H': 'Horizontal', 'V': 'Vertical'} #fp_name_format_string = "Conn_DIN41612_{size:s}{num_pins:d}{gender:s} #fp_name_format_string = "DIN41612_{size:s}{num_pins:d}{gender:s}_{num_rows:d}x{pins_per_row:d}_{orientation:s}" fp_name_format_string = "DIN41612_{size:s}_{num_rows:d}x{pins_per_row:d}_{orientation:s}" def AllPins(row, col): return True def EvenColPins(row, col): return not bool(col % 2) def OptionalPin(kicad_mod, row, col, row_step, col_step, pin_pad, pin_drill, opt_cb, rotate = False): if not opt_cb(row, col): return shape = Pad.SHAPE_CIRCLE if col == 1 and row == ROW_IDENTIFIER[0]: shape = Pad.SHAPE_RECT if rotate: x = row_step * (ord(row) - ord(ROW_IDENTIFIER[0])) y = -col_step*(col-1) else: x = col_step*(col-1) y = row_step * (ord(row) - ord(ROW_IDENTIFIER[0])) kicad_mod.append(Pad(number= row + str(col), type=Pad.TYPE_THT, shape=shape, at=[x, y], size=pin_pad, drill=pin_drill, layers=Pad.LAYERS_THT)) # don't know if KLC allows 3d compositing at all #pin_model = "Pin_Headers.3dshapes/Pin_Header_Straight_1x01_Pitch2.54mm.wrl" #inch = 25.4 #pos_inch = [x/inch, -y/inch, 0] #kicad_mod.append(Model(filename=pin_model, at=pos_inch, scale=[1, 1, 1], rotate=[0, 0, 0])) def BFemale(size, pin_cb, more_description): # This footprint is rotated by 90° counter clockwise # so columns are in x-direction and rows are in y-direction colss = [32, 16, 10] cols = colss[size] npth_b_offset_x = -0.3 # ERNI and ept npth_steps = [90, 50, 34.76] # ERNI and ept npth_step = npth_steps[size] npth_drill = 2.8 # ERNI and ept col_step = -2.54 # ERNI and ept row_step = 2.54 # ERNI and ept pin_drill = 1 # ERNI and ept pin_pad = 1.7 # same as module pinheader outer_lengths = [95, 55, 39.76] # maximum value from ERNI and ept outer_length = outer_lengths[size] outer_width = 8.1 # ERNI and ept jack_width = 5.95 # ERNI: 6(-0.1), ept: 5.95(±0.05) jack_lengths = [85, 44.4, 29.1] # ERNI jack_length = jack_lengths[size] notch_depth = 1 # ERNI and ept notch_bottom_offset = -3 # ERNI and ept mid_x = 0.5 * row_step mid_y = -0.5 * col_step * (cols - 1) # ------ Init ------ pin_count = 0; for col in range(1, cols + 1): pin_count += int(pin_cb('A', col)) pin_count += int(pin_cb('B', col)) #size_names = ["B", "2B", "3B"] size_names = ["B", "B2", "B3"] footprint_name = fp_name_format_string.format( size=size_names[size], num_pins=pin_count, gender="F", num_rows=2, pins_per_row=pin_count//2, orientation=ORIENTATION['V']) # init kicad footprint kicad_mod = Footprint(footprint_name) size_descs = ["B", "B/2", "B/3"] kicad_mod.setDescription("DIN 41612 connector, type " + size_descs[size] + ", vertical, " + str(cols) + " pins wide, 2 rows" + more_description) kicad_mod.setTags("DIN 41512 IEC 60603 " + size_descs[size]) # ------ Pins and holes ------ for col in range(1, cols + 1): OptionalPin(kicad_mod, ROW_IDENTIFIER[0], col, row_step, col_step, pin_pad, pin_drill, pin_cb, True) OptionalPin(kicad_mod, ROW_IDENTIFIER[1], col, row_step, col_step, pin_pad, pin_drill, pin_cb, True) # non-plated drill holes, assumed to be equally distant to pins npth_x = row_step + npth_b_offset_x npth_y_left = mid_y - npth_step * 0.5 npth_y_right = mid_y + npth_step * 0.5 kicad_mod.append(Pad(number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[npth_x, npth_y_left], size=npth_drill, drill=npth_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[npth_x, npth_y_right], size=npth_drill, drill=npth_drill, layers=Pad.LAYERS_NPTH)) # ------ Courtyard ------ # KLC: connectors should have 0.5mm clearance kicad_mod.append(RectLine( start=[mid_x - outer_width/2 - 0.5, mid_y - outer_length/2 - 0.5], end=[mid_x + outer_width/2 + 0.5, mid_y + outer_length/2 + 0.5], layer='F.CrtYd')) # ------ Fabrication layer ------ j_t_x = mid_x - jack_width * 0.5 # jack top j_b_x = mid_x + jack_width * 0.5 # jack bottom j_l_y = mid_y - jack_length * 0.5 # jack left j_r_y = mid_y + jack_length * 0.5 # jack right n_x = j_b_x + notch_bottom_offset # notch n_l_y = j_l_y + notch_depth # notch left n_r_y = j_r_y - notch_depth # notch right jack_notch_left = [[j_t_x, n_l_y], [j_t_x, j_l_y], [n_x, j_l_y], [n_x, n_l_y], [j_b_x, n_l_y]] jack_notch_right = [[j_b_x, n_r_y], [n_x, n_r_y], [n_x, j_r_y], [j_t_x, j_r_y], [j_t_x, n_r_y]] pin_a1_arrow = [ # form taken from module Connectors_Molex [mid_x - outer_width/2 - 0.2, 0.0], [mid_x - outer_width/2 - 0.8, -0.3], [mid_x - outer_width/2 - 0.8, 0.3], [mid_x - outer_width/2 - 0.2, 0.0], ] kicad_mod.append(PolygoneLine( polygone=jack_notch_left + jack_notch_right + [jack_notch_left[0]], layer='F.Fab')) kicad_mod.append(PolygoneLine( polygone=pin_a1_arrow, width=0.12, layer='F.Fab')) kicad_mod.append(Text( type='value', text=footprint_name, at=[mid_x, mid_y + outer_length/2 + 1.3], layer='F.Fab')) # Very small Reference Designator to fit between the pins. kicad_mod.append(Text( type='user', text='%R', at=[mid_x, mid_y], size=[0.6, 0.6], thickness=0.07, layer='F.Fab')) # ------ Silk screen ------ # assume plastic part to be centered around the pins # silk screen must be visible, so add 0.1 mm kicad_mod.append(RectLine( start=[mid_x - outer_width/2 - 0.1, mid_y - outer_length/2 - 0.1], end=[mid_x + outer_width/2 + 0.1, mid_y + outer_length/2 + 0.1], width=0.15, layer='F.SilkS')) kicad_mod.append(PolygoneLine( polygone=jack_notch_left, width=0.15, layer='F.SilkS')) kicad_mod.append(PolygoneLine( polygone=jack_notch_right, width=0.15, layer='F.SilkS')) kicad_mod.append(PolygoneLine( polygone=pin_a1_arrow, width=0.12, layer='F.SilkS')) kicad_mod.append(Text( type='reference', text='REF**', at=[mid_x, mid_y - outer_length/2 - 1], layer='F.SilkS')) # ------ 3D reference ------ # in case someone wants to make a model kicad_mod.append(Model( filename="${KISYS3DMOD}/Connectors_IEC_DIN.3dshapes/" + footprint_name + ".wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # ------ Output ------ file_handler = KicadFileHandler(kicad_mod) output_dir = '{lib_name:s}.pretty/'.format(lib_name=LIBRARY_NAME) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler.writeFile(filename) def BMale(size, pin_cb, more_description): colss = [32, 16, 10] cols = colss[size] npth_a_offset_y = -2.54 # ERNI npth_steps = [88.9, 48.26, 33.02] # ERNI npth_step = npth_steps[size] npth_drill = 2.8 # ERNI col_step = 2.54 # ERNI and ept row_step = 2.54 # ERNI and ept pin_drill = 1 # ERNI and ept pin_pad = 1.7 # same as module pinheader jack_to_npth = 10.2 # ERNI jack_widths = [87.5, 47, 31.7] # ERNI jack_width = jack_widths[size] jack_to_eyelet = 12.7 eyelet_spans = [94, 53.5, 38.1] # ERNI or ept eyelet_span = eyelet_spans[size] board_edge_to_a = 5.3 # ERNI mid_x = 0.5 * col_step * (cols - 1) mid_y = 0.5 * row_step # ------ Init ------ pin_count = 0; for col in range(1, cols + 1): pin_count += int(pin_cb('A', col)) pin_count += int(pin_cb('B', col)) #size_names = ["B", "2B", "3B"] size_names = ["B", "B2", "B3"] footprint_name = fp_name_format_string.format( size=size_names[size], num_pins=pin_count, gender="M", num_rows=2, pins_per_row=pin_count//2, orientation=ORIENTATION['H']) # init kicad footprint kicad_mod = Footprint(footprint_name) size_descs = ["B", "B/2", "B/3"] kicad_mod.setDescription("DIN 41612 connector, type " + size_descs[size] + ", horizontal, " + str(cols) + " pins wide, 2 rows" + more_description) kicad_mod.setTags("DIN 41512 IEC 60603 " + size_descs[size]) # ------ Pins and holes ------ for col in range(1, cols + 1): OptionalPin(kicad_mod, ROW_IDENTIFIER[0], col, row_step, col_step, pin_pad, pin_drill, pin_cb) OptionalPin(kicad_mod, ROW_IDENTIFIER[1], col, row_step, col_step, pin_pad, pin_drill, pin_cb) # non-plated drill holes, assumed to be equally distant to pins npth_x_left = mid_x - npth_step * 0.5 npth_x_right = mid_x + npth_step * 0.5 npth_y = npth_a_offset_y kicad_mod.append(Pad(number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[npth_x_left, npth_y], size=npth_drill, drill=npth_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[npth_x_right, npth_y], size=npth_drill, drill=npth_drill, layers=Pad.LAYERS_NPTH)) # ------ Silk screen ------ # assume plastic part to be centered around the pins eyelet_border = jack_to_eyelet - jack_to_npth package_outline = [ [mid_x - eyelet_span/2 + 2 * eyelet_border, npth_y + eyelet_border - pin_drill/2], # x: guess [mid_x - eyelet_span/2 + 2 * eyelet_border, npth_y + eyelet_border], # x: guess [mid_x - eyelet_span/2, npth_y + eyelet_border], [mid_x - eyelet_span/2, npth_y - eyelet_border], # y: guess, not ept [mid_x - jack_width/2, npth_y - eyelet_border], # y: guess, not ept [mid_x - jack_width/2, npth_y - jack_to_npth], # --- mirror line --- [mid_x + jack_width/2, npth_y - jack_to_npth], [mid_x + jack_width/2, npth_y - eyelet_border], # y: guess, not ept [mid_x + eyelet_span/2, npth_y - eyelet_border], # y: guess, not ept [mid_x + eyelet_span/2, npth_y + eyelet_border], [mid_x + eyelet_span/2 - 2 * eyelet_border, npth_y + eyelet_border], # x: guess [mid_x + eyelet_span/2 - 2 * eyelet_border, npth_y + eyelet_border - pin_drill/2], # x: guess ] # silkscreen is offset by 0.1 mm to be visible with component placed silkscreen_left = [ [package_outline[ 0][0] + 0.1, package_outline[ 0][1] + 0.1], [package_outline[ 1][0] + 0.1, package_outline[ 1][1] + 0.1], [package_outline[ 2][0] - 0.1, package_outline[ 2][1] + 0.1], [package_outline[ 3][0] - 0.1, package_outline[ 3][1]], # can not draw further, it would leave the pcb ] silkscreen_right = [ [package_outline[11][0] - 0.1, package_outline[11][1] + 0.1], [package_outline[10][0] - 0.1, package_outline[10][1] + 0.1], [package_outline[ 9][0] + 0.1, package_outline[ 9][1] + 0.1], [package_outline[ 8][0] + 0.1, package_outline[ 8][1]], # can not draw further, it would leave the pcb ] pin_a1_arrow = [ # form taken from module Connectors_Molex [-pin_pad/2 - 0.5 - 0.0, 0.0], [-pin_pad/2 - 0.5 - 0.6, -0.3], [-pin_pad/2 - 0.5 - 0.6, 0.3], [-pin_pad/2 - 0.5 - 0.0, 0.0] ] kicad_mod.append(PolygoneLine( polygone=silkscreen_left, width=0.15, layer='F.SilkS')) kicad_mod.append(PolygoneLine( polygone=silkscreen_right, width=0.15, layer='F.SilkS')) kicad_mod.append(PolygoneLine( polygone=pin_a1_arrow, width=0.12, layer='F.SilkS')) kicad_mod.append(Text( type='reference', text='REF**', at=[mid_x - npth_step * 0.5, row_step * 0.5], layer='F.SilkS')) # ------ Fabrication layer ------ kicad_mod.append(PolygoneLine( polygone = package_outline + [package_outline[0]], layer = 'F.Fab')) kicad_mod.append(Text( type='value', text=footprint_name, at=[mid_x, npth_y + jack_to_npth - 1.3], layer='F.Fab')) kicad_mod.append(Text( type='user', text='%R', at=[mid_x, npth_y], size=[1, 1], thickness=0.15, layer='F.Fab')) # ------ Courtyard ------ # KLC: connectors should have 0.5mm clearance courtyard = [ [-pin_pad/2 - 0.5, row_step + pin_pad/2 + 0.5], [-pin_pad/2 - 0.5, package_outline[10][1] + 0.5], [package_outline[ 2][0] - 0.5, package_outline[ 2][1] + 0.5], [package_outline[ 3][0] - 0.5, package_outline[ 3][1] - 0.5], [package_outline[ 4][0] - 0.5, package_outline[ 4][1] - 0.5], [package_outline[ 5][0] - 0.5, package_outline[ 5][1] - 0.5], [package_outline[ 6][0] + 0.5, package_outline[ 6][1] - 0.5], [package_outline[ 7][0] + 0.5, package_outline[ 7][1] - 0.5], [package_outline[ 8][0] + 0.5, package_outline[ 8][1] - 0.5], [package_outline[ 9][0] + 0.5, package_outline[ 9][1] + 0.5], [package_outline[10][0] - 0.5, package_outline[10][1] + 0.5], [(cols - 1) * col_step + pin_pad/2 + 0.5, package_outline[ 1][1] + 0.5], [(cols - 1) * col_step + pin_pad/2 + 0.5, row_step + pin_pad/2 + 0.5], ] kicad_mod.append(PolygoneLine( polygone = courtyard + [courtyard[0]], layer = 'F.CrtYd')) # ------ Board edge ------ kicad_mod.append(Line( start = [mid_x - jack_width/2, -board_edge_to_a], end = [mid_x + jack_width/2, -board_edge_to_a], width = 0.08, layer = 'Dwgs.User')) kicad_mod.append(Line( start = [mid_x, -board_edge_to_a - 1.5], end = [mid_x, -board_edge_to_a - 0.1], width = 0.1, layer = 'Cmts.User')) kicad_mod.append(PolygoneLine( polygone = [ [mid_x - 0.2, -board_edge_to_a - 0.6], [mid_x, -board_edge_to_a - 0.1], [mid_x + 0.2, -board_edge_to_a - 0.6], ], width = 0.1, layer = 'Cmts.User')) kicad_mod.append(Text( type='user', text='Board edge', at=[mid_x, -board_edge_to_a - 2], size=[0.7, 0.7], thickness=0.1, layer='Cmts.User')) # ------ 3D reference ------ # in case someone wants to make a model kicad_mod.append(Model( filename="{prefix}{lib_name}.3dshapes/{fp_name}.wrl".format(prefix = '${KISYS3DMOD}/', lib_name=LIBRARY_NAME, fp_name=footprint_name), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # ------ Output ------ file_handler = KicadFileHandler(kicad_mod) output_dir = '{lib_name:s}.pretty/'.format(lib_name=LIBRARY_NAME) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler.writeFile(filename) BFemale(0, AllPins, ", full configuration") BFemale(0, EvenColPins, ", even columns") BFemale(1, AllPins, ", full configuration") BFemale(1, EvenColPins, ", even columns") BFemale(2, AllPins, ", full configuration") BFemale(2, EvenColPins, ", even columns") BMale(0, AllPins, ", full configuration") BMale(0, EvenColPins, ", even columns") BMale(1, AllPins, ", full configuration") BMale(1, EvenColPins, ", even columns") BMale(2, AllPins, ", full configuration") BMale(2, EvenColPins, ", even columns") # output kicad model ================================================ FILE: scripts/Connector/Connector_JAE/conn_ffc_jae_ff08.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from footprint_keepout_area import addRectangularKeepout pinrange = [25, 29, 41, 51, 71, 81] series = "" series_long = 'JAE 0.2mm pitch, 1mm overall height FFC/FPC connector' manufacturer = 'JAE' orientation = 'H' number_of_rows = 2 datasheet='http://www.jae.com/z-en/pdf_download_exec.cfm?param=SJ108178.pdf' conn_category = "FFC-FPC" lib_by_conn_category = True part_code = "FF08{:02d}SA1" # def get_name(pin_count): # return 'Molex-502250-{0}91_2Rows-{0}Pins_P0.3mm_Horizontal'.format(pin_count) cable_pitch = 0.2 odd_pad_size = (0.55, 0.18) # bottom even_pad_size = (0.7, 0.18) # top def make_module(pin_count, configuration): pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] mpn = part_code.format(pin_count) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_unequal_row_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins=pin_count, mounting_pad = "", pitch=cable_pitch*2, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Circuits ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pin_count, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) pad_to_pad_inside = 2 pad_to_pad_outside = pad_to_pad_inside + odd_pad_size[0] + even_pad_size[0] row_spacing = pad_to_pad_outside - odd_pad_size[0]/2 - even_pad_size[0]/2 odd_pad_x = -pad_to_pad_outside/2 + odd_pad_size[0]/2 even_pad_x = odd_pad_x + row_spacing B = cable_pitch * (pin_count - 1) A = B + (7.05-4.8) bar_width_max = 2*3.8 bar_chamfer_y = 1 bar_from_side_min = 0.1 bar_width = A - 2*bar_from_side_min if bar_width > bar_width_max: bar_width = bar_width_max body_edge = { 'top': -A/2, 'bottom': A/2, 'left': odd_pad_x - odd_pad_size[0]/2 + 0.35 } body_edge['right'] = body_edge['left'] + 2.85 bar_down_edge = body_edge['left'] + 3.23 bounding_box = { 'top': body_edge['top'], 'bottom': body_edge['bottom'], 'left': odd_pad_x - odd_pad_size[0]/2, 'right': bar_down_edge } kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.Fab", width=configuration['fab_line_width'] )) kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['right'], 'y': -bar_width/2}, {'x': bar_down_edge, 'y': -bar_width/2 + bar_chamfer_y}, {'x': bar_down_edge, 'y': bar_width/2 - bar_chamfer_y}, {'x': body_edge['right'], 'y': bar_width/2} ], layer="F.Fab", width=configuration['fab_line_width'] )) odd_pins_outside = B/2 + odd_pad_size[1]/2 + pad_silk_off silk_outline = [ {'x': body_edge['left']-off, 'y':odd_pins_outside}, {'x': body_edge['left']-off, 'y':body_edge['bottom']+off}, {'x': body_edge['right'] + off, 'y':body_edge['bottom']+off}, {'x': body_edge['right'] + off, 'y': bar_width/2 + off}, {'x': bar_down_edge + off, 'y': bar_width/2 - bar_chamfer_y + off}, {'x': bar_down_edge + off, 'y': 0} ] kicad_mod.append(PolygoneLine( polygone=silk_outline, layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(PolygoneLine( polygone=silk_outline, y_mirror=0, layer="F.SilkS", width=configuration['silk_line_width'] )) even_pins = pin_count//2 odd_pins = pin_count - even_pins kicad_mod.append(PadArray( center=[odd_pad_x,0], pincount=odd_pins, initial=1, increment=2, y_spacing=2*cable_pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=odd_pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray( center=[even_pad_x, 0], pincount=even_pins, initial=2, increment=2, y_spacing=2*cable_pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=even_pad_size, layers=Pad.LAYERS_SMT)) pin1_y = -B/2 ps1_m = 0.3 p1s_x = bounding_box['left'] - pad_silk_off pin = [ {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y-ps1_m/2}, {'x': p1s_x, 'y': pin1_y}, {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y+ps1_m/2}, {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y-ps1_m/2} ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) sl=0.6 pin = [ {'x': body_edge['left'], 'y': pin1_y-sl/2}, {'x': body_edge['left'] + sl/sqrt(2), 'y': pin1_y}, {'x': body_edge['left'], 'y': pin1_y+sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pincount in pinrange: make_module(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JAE/conn_jae_LY20_tht_side.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from footprint_keepout_area import addRectangularKeepout pins_per_row_range = range(2,23) series = "" series_long = 'LY 20 series connector' manufacturer = 'JAE' orientation = 'H' number_of_rows = 2 datasheet='http://www.jae.com/z-en/pdf_download_exec.cfm?param=SJ038187.pdf' part_code = "LY20-{:d}P-DLT1" # def get_name(pin_count): # return 'Molex-502250-{0}91_2Rows-{0}Pins_P0.3mm_Horizontal'.format(pin_count) pitch = 2 drill = 0.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pitch_row = 2 pad_size = [pitch_row - pad_to_pad_clearance, pitch - pad_to_pad_clearance] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring ROW_NAMES = ('a','b') def incrementPadNumber(old_number): return old_number[0] + str(int(old_number[1:])+1) if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL def make_module(pins_per_row, configuration): pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] mpn = part_code.format(pins_per_row*2) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Circuits ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) Wi = 4.8 T = 2.8 W = Wi + T body_edge = {} body_edge['right'] = pitch_row + 2.2 + T body_edge['left'] = body_edge['right'] - W A = (pins_per_row-1)*pitch B = (A - 8) if A >= 8 else 0 C = (A - 4.6) if A >= 4.6 else 0 D = A + 2.6 E = A + 3.6 body_edge['top'] = -(E - A)/2 body_edge['bottom'] = body_edge['top'] + E bounding_box = body_edge.copy() ############################## Pins ############################### optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( initial=ROW_NAMES[row_idx]+'1', start=[(row_idx)*pitch_row, 0], y_spacing=pitch, pincount=pins_per_row, increment=incrementPadNumber, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, tht_pad1_id=ROW_NAMES[0]+'1', **optional_pad_params)) ############################ Outline ############################## kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.Fab", width=configuration['fab_line_width'] )) r_no_silk = max(pad_size)/2 + pad_silk_off dx = abs(body_edge['left']) + off pin_center_silk_y = 0 if dx >= r_no_silk else sqrt(r_no_silk**2-dx**2) pin1_center_silk_y = pad_size[1]/2 + pad_silk_off YCb = A/2+C/2 YCt = A/2-C/2 YBb = A/2+B/2 poly_silk_b = [ {'x': body_edge['left']-off, 'y': body_edge['bottom']+off}, {'x': body_edge['right']+off, 'y': body_edge['bottom']+off}, {'x': body_edge['right']+off, 'y': YCb}, ] if C > 0: poly_silk_b.extend([ {'x': body_edge['right']-T, 'y': YCb}, {'x': body_edge['right']-T, 'y': A/2}, ]) kicad_mod.append(PolygoneLine(polygone=poly_silk_b, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_b, y_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) if pin_center_silk_y == 0: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['top']], end=[body_edge['left']-off, body_edge['bottom']], layer="F.SilkS", width=configuration['silk_line_width'] )) else: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['top']-off], end=[body_edge['left']-off, -pin1_center_silk_y], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[body_edge['left']-off, pin1_center_silk_y], end=[body_edge['left']-off, pitch-pin_center_silk_y], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[body_edge['left']-off, A+pin_center_silk_y], end=[body_edge['left']-off, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) for i in range(1, pins_per_row-1): yt = i*pitch + pin_center_silk_y yb = (i+1)*pitch - pin_center_silk_y kicad_mod.append(Line( start=[body_edge['left']-off, yt], end=[body_edge['left']-off, yb], layer="F.SilkS", width=configuration['silk_line_width'] )) x1 = body_edge['right']-T pin_w = 0.5 pin_L = 2.7 pin_chamfer_x = pin_w/3 if B>0: x2 = x1 + 2 # estimated from drawing poly = [ {'x': x2, 'y':YCb}, {'x': x2, 'y':YBb+pin_w/2} ] kicad_mod.append(PolygoneLine(polygone=poly, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly, y_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) #pins if C>0: for i in range(pins_per_row): ypc = i*pitch x3 = x1 + pin_L x2 = x3 - pin_chamfer_x if ypc - pin_w/2 >= YCt and ypc + pin_w/2 <= YCb: pin_poly = [ {'x': x1, 'y': ypc-pin_w/2}, {'x': x2, 'y': ypc-pin_w/2}, {'x': x3, 'y': ypc}, {'x': x2, 'y': ypc+pin_w/2}, {'x': x1, 'y': ypc+pin_w/2} ] kicad_mod.append(PolygoneLine(polygone=pin_poly, layer="F.SilkS", width=configuration['silk_line_width'])) ########################### Pin 1 ################################# p1s_sl = 2 p1s_off = off + 0.3 kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'] + p1s_sl, 'y': body_edge['top'] - p1s_off}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] - p1s_off}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] + p1s_sl} ], layer="F.SilkS", width=configuration['silk_line_width'])) p1f_sl = 1 kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'], 'y': p1f_sl/2}, {'x': body_edge['left'] + p1f_sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': -p1f_sl/2} ], layer="F.Fab", width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: make_module(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_JAE/conn_jae_LY20_tht_top.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from footprint_keepout_area import addRectangularKeepout pins_per_row_range = range(2,23) series = "" series_long = 'LY 20 series connector' manufacturer = 'JAE' orientation = 'V' number_of_rows = 2 datasheet='http://www.jae.com/z-en/pdf_download_exec.cfm?param=SJ103130.pdf' part_code = "LY20-{:d}P-DT1" # def get_name(pin_count): # return 'Molex-502250-{0}91_2Rows-{0}Pins_P0.3mm_Horizontal'.format(pin_count) pitch = 2 drill = 0.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pitch_row = 2 pad_size = [pitch_row - pad_to_pad_clearance, pitch - pad_to_pad_clearance] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring ROW_NAMES = ('a','b') def incrementPadNumber(old_number): return old_number[0] + str(int(old_number[1:])+1) if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL def make_module(pins_per_row, configuration): pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] mpn = part_code.format(pins_per_row*2) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Circuits ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) W = 5.3 Wi = 4.2 body_edge = {} body_edge['left'] = -(W - pitch_row)/2 body_edge['right'] = body_edge['left'] + W A = (pins_per_row-1)*pitch B = (A - 8) if A >= 8 else 0 C = (A - 4.6) if A >= 4.6 else 0 D = A + 2.6 E = A + 3.6 body_edge['top'] = -(E - A)/2 body_edge['bottom'] = body_edge['top'] + E bounding_box = body_edge.copy() ############################## Pins ############################### optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( initial=ROW_NAMES[row_idx]+'1', start=[(row_idx)*pitch_row, 0], y_spacing=pitch, pincount=pins_per_row, increment=incrementPadNumber, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, tht_pad1_id=ROW_NAMES[0]+'1', **optional_pad_params)) ############################ Outline ############################## kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.Fab", width=configuration['fab_line_width'] )) kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer="F.SilkS", width=configuration['silk_line_width'], offset=off )) # inside CW = 1 xil = body_edge['left'] + (W - Wi)/2 xir =xil + Wi yit = body_edge['top'] + (E-D)/2 yt1 = A/2-C/2 yb1 = A/2+C/2 yt2 = A/2-B/2 poly_left_t = [ {'x': pitch_row-CW/2, 'y': body_edge['top'] - off}, {'x': pitch_row-CW/2, 'y': yit}, {'x': xil, 'y': yit}, {'x': xil, 'y': yt1}, {'x': body_edge['left']-off, 'y': yt1}, ] if C == 0: del poly_left_t[-1] kicad_mod.append(PolygoneLine(polygone=poly_left_t, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_left_t, y_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) poly_right_t = [ {'x': pitch_row+CW/2, 'y': body_edge['top'] - off}, {'x': pitch_row+CW/2, 'y': yit}, {'x': xir, 'y': yit}, {'x': xir, 'y': yt2}, {'x': body_edge['right']+off, 'y': yt2}, ] if B == 0: del poly_right_t[-1] else: kicad_mod.append(Line( start={'x': body_edge['right']+off, 'y': yt1}, end={'x': xir, 'y': yt1}, layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start={'x': body_edge['right']+off, 'y': yb1}, end={'x': xir, 'y': yb1}, layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(PolygoneLine(polygone=poly_right_t, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_right_t, y_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) ########################### Pin 1 ################################# p1s_sl = 2 p1s_off = off + 0.3 kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'] + p1s_sl, 'y': body_edge['top'] - p1s_off}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] - p1s_off}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] + p1s_sl} ], layer="F.SilkS", width=configuration['silk_line_width'])) p1f_sl = 1 kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'], 'y': p1f_sl/2}, {'x': body_edge['left'] + p1f_sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': -p1f_sl/2} ], layer="F.Fab", width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: make_module(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_JAE/helpers.py ================================================ def roundToBase(value, base): if base == 0: return value return round(value/base) * base ================================================ FILE: scripts/Connector/Connector_JST/00-SMD footprint generators can be found in Connector_SMD_single_row_plus_mounting_pad.md ================================================ The following connector footprints are generated in the generic scirpt located in ../Connector_SMD_single_row_plus_mounting_pad/ - 'ACH' - 'AUH' - 'LEA' - 'GH' - 'PH' (only SMD version = `*PH-SM4*`) - 'SFH' - 'SHL' - 'SH' - 'SUR' - 'XAG' - 'ZE' ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_J2100_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "J2100" manufacturer = 'JST' orientation = 'H' number_of_rows = 2 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eJFA-J2000.pdf' pitch = 2.50 #pin_range = [3,4,5,6,8,10] #number of pins in each row pin_range = [6, 8, 10, 12, 16, 20] row_pitch = 2.50 #FP name strings part_base = "S{n:02}B-J21DK-GG{s}R" #JST part number format string drill = 0.86 # 0.85 -0.03/+0.05 -> 0.86 +/-0.04 mh_drill = 2 mh_size = 3.4 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 min_annular_ring = 0.15 ROW_NAMES = ('a','b') def incrementPadNumber(old_number): return old_number[0] + str(int(old_number[1:])+1) #FP description and tags def generate_one_footprint(pins, configuration, keying): #calculate fp dimensions pins_per_row = int(pins / number_of_rows) A = (pins_per_row - 1) * pitch B = A + 5.2 #generate the name mpn = part_base.format(n=pins, s=keying) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) print('Building footprint: {}'.format(footprint_name)) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) pad_size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*pad_copper_y_solder_length: pad_size[1] = drill + 2*pad_copper_y_solder_length if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( initial=row_idx*pins_per_row+1, start=[0, -(row_idx)*row_pitch], x_spacing=pitch, pincount=pins_per_row, increment=1, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A/2 - B/2 x2 = x1 + B y1 = -2.5 - 0.62 y2 = y1 + 17.8 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline around the footprint kicad_mod.append(RectLine(start=[x1,y1], end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if y1 < -row_pitch - pad_size[1]/2: cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) else: cy1 = roundToBase(-row_pitch - pad_size[1]/2-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #outline side = [ {'x': -1,'y': y1}, {'x': x1,'y': y1}, {'x': x1,'y': y2}, {'x': A/2,'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=side, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=side, x_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) #add mounting holes if pins == 6: m = Pad(at=[pitch,7],layers=Pad.LAYERS_THT,shape=Pad.SHAPE_CIRCLE,type=Pad.TYPE_THT,size=mh_size,drill=mh_drill) kicad_mod.append(m) else: m1 = Pad(at=[0,7],layers=Pad.LAYERS_THT,shape=Pad.SHAPE_CIRCLE,type=Pad.TYPE_THT,size=mh_size,drill=mh_drill) m2 = Pad(at=[A,7],layers=Pad.LAYERS_THT,shape=Pad.SHAPE_CIRCLE,type=Pad.TYPE_THT,size=mh_size,drill=mh_drill) kicad_mod.append(m1) kicad_mod.append(m2) #add p1 marker px = -3 m = 0.3 marker = [ {'x': px,'y': 0}, {'x': px-2*m,'y': m}, {'x': px-2*m,'y': -m}, {'x': px,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=marker, layer="F.SilkS", width=configuration['silk_line_width'])) sl = 1 marker = [ {'x': body_edge['left'],'y': sl/2}, {'x': body_edge['left'] +sl/sqrt(2),'y': 0}, {'x': body_edge['left'],'y': -sl/2} ] kicad_mod.append(PolygoneLine(polygone=marker, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible #for pins_per_row in pin_range: #generate_one_footprint(pins_per_row, configuration) for pin_count in pin_range: generate_one_footprint(pin_count, configuration, 'X') ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_J2100_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "J2100" manufacturer = 'JST' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eJFA-J2000.pdf' pitch = 2.50 #pin_range = [3,4,5,6,8,10] #number of pins in each row pin_range = [6, 8, 10, 12, 16, 20] row_pitch = 4 #FP name strings part_base = "B{n:02}B-J21DK-GG{s}R" #JST part number format string drill = 0.86 # 0.85 -0.03/+0.05 -> 0.86 +/-0.04 mh_drill = 2 mh_size = 3 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 min_annular_ring = 0.15 #pin1_row_to_mh = 'far' # 'near' ROW_NAMES = ('a','b') def incrementPadNumber(old_number): return old_number[0] + str(int(old_number[1:])+1) #FP description and tags def generate_one_footprint(pins, configuration, keying): #calculate fp dimensions pins_per_row = int(pins / number_of_rows) A = (pins_per_row - 1) * pitch B = A + 5.2 mpn = part_base.format(n=pins, s=keying) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_dual_pitch_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch_x=pitch, pitch_y=row_pitch, orientation=orientation_str) print('Building footprint: {}'.format(footprint_name)) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) pad_size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*pad_copper_y_solder_length: pad_size[1] = drill + 2*pad_copper_y_solder_length if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): #if pin1_row_to_mh == 'near': if keying == 'X': position_y = (row_idx)*row_pitch elif keying == 'Y': position_y = -(row_idx)*row_pitch kicad_mod.append(PadArray( initial=row_idx*pins_per_row+1, start=[0, position_y], x_spacing=pitch, pincount=pins_per_row, increment=1, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A/2 - B/2 x2 = x1 + B y1 = -4.48 #if pin1_row_to_mh == 'near': if keying == 'Y': y1 -= row_pitch y2 = y1 + 14.4 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline around the footprint kicad_mod.append(RectLine(start=[x1,y1], end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #outline ol = RectLine(start=[x1,y1], end=[x2,y2], layer="F.SilkS", width=configuration['silk_line_width']) kicad_mod.append(ol) #courtyard #add mounting holes mh_y = 3.3 #if pin1_row_to_mh != 'near': if keying == 'X': mh_y += row_pitch m1 = Pad(at=[0, mh_y],layers=Pad.LAYERS_THT,shape=Pad.SHAPE_CIRCLE,type=Pad.TYPE_THT,size=3, drill=2) m2 = Pad(at=[A, mh_y],layers=Pad.LAYERS_THT,shape=Pad.SHAPE_CIRCLE,type=Pad.TYPE_THT,size=3, drill=2) kicad_mod.append(m1) kicad_mod.append(m2) #add p1 marker px = -3 m = 0.3 marker = [ {'x': px,'y': 0}, {'x': px-2*m,'y': m}, {'x': px-2*m,'y': -m}, {'x': px,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=marker, layer="F.SilkS", width=configuration['silk_line_width'])) sl = 1 marker = [ {'x': body_edge['left'],'y': sl/2}, {'x': body_edge['left'] +sl/sqrt(2),'y': 0}, {'x': body_edge['left'],'y': -sl/2} ] kicad_mod.append(PolygoneLine(polygone=marker, layer='F.Fab', width=configuration['fab_line_width'])) #line offset o o = 1 ya = o yb = -o-row_pitch #if pin1_row_to_mh != 'near': if keying == 'X': ya += row_pitch yb = -o #draw lines between pin pairs for i in range(pins_per_row - 1): x = (i + 0.5) * pitch kicad_mod.append(Line(start=[x,ya], end=[x,yb], width=configuration['fab_line_width'], layer='F.Fab')) #draw the inside of the connector #connector thickness t t = 0.45 #notch size n n = 1.2 inside = [ {'x': A/2 - n/2,'y': y1}, {'x': A/2 - n/2,'y': y1 + t}, {'x': x1 + t,'y': y1 + t}, {'x': x1 + t,'y': y2 - t}, {'x': x1 + t + n,'y': y2 - t}, {'x': x1 + t + n,'y': y2 - 2 * t}, {'x': A/2,'y': y2 - 2 * t} ] kicad_mod.append(PolygoneLine(polygone = inside, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone = inside, x_mirror=A/2, layer="F.SilkS", width=configuration['silk_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible #for pins_per_row in pin_range: #generate_one_footprint(pins_per_row, configuration) for pin_count in pin_range: generate_one_footprint(pin_count, configuration, 'X') #generate_one_footprint(pin_count, configuration, 'Y') ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_JWPF_tht_top.py ================================================ #!/usr/bin/env python3 import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "JWPF" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eJWPF1.pdf' part_base = "B{n:02}B-JWPF-SK-R" #JST part number format string prefix = "JST_JWPF_" pitch = 2.00 pad_to_pad_clearance = 0.8 pad_copper_x_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 # Connector Dimensions tab_width = 7.0 row_spacing = 4.0 pad_drill = 1.0 mount_hole_size = 1.15 mount_hole_offset_x = 1.5 # Width of connector jwpf_widths = { 2 : 8.1, 3 : 8.4, 4 : 8.4, 6 : 12.8, 8 : 12.5 } jwpf_lengths = { 2 : 7, 3 : 9, 4 : 11, 6 : 9.8, 8 : 11.8 } pin_range = [2, 3, 4, 6, 8] def generate_one_footprint(pincount, configuration): if pincount in [6, 8]: number_of_rows = 2 pin_per_row = int(pincount / 2) else: number_of_rows = 1 pin_per_row = pincount mpn = part_base.format(n=pincount) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pin_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) conn_width = jwpf_widths[pincount] conn_length = jwpf_lengths[pincount] mount_hole_offset_y = 2.05 if number_of_rows == 1 else 2.45 # Add texts x_mid = (number_of_rows-1) * row_spacing / 2 y_mid = (pin_per_row - 1) * pitch / 2.0 # Connector outline y1 = y_mid - conn_length / 2 y2 = y_mid + conn_length / 2 x1 = -5.4 # measured from 3D model alignment x2 = x1 + conn_width body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} y_ref = -3 if number_of_rows == 1 else -4 pad_size = [pad_drill + 2*pad_copper_x_solder_length, pitch - pad_to_pad_clearance] if number_of_rows > 1: if pad_size[0] - pad_drill > 2*pad_copper_x_solder_length: pad_size[0] = pad_drill + 2*pad_copper_x_solder_length if pad_size[0] - pad_drill < 2*min_annular_ring: pad_size[0] = pad_drill + 2*min_annular_ring if pad_size[1] - pad_drill < 2*min_annular_ring: pad_size[1] = pad_drill + 2*min_annular_ring if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT # Create pins for i in range(number_of_rows): kicad_mod.append(PadArray( initial=1+i*pin_per_row, start=[i*row_spacing, 0], pincount=pin_per_row, y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=pad_drill, layers=Pad.LAYERS_THT, **optional_pad_params)) # Add mounting hole mx = -mount_hole_offset_x my = (pin_per_row - 1) * pitch + mount_hole_offset_y kicad_mod.append(Pad(at=[mx, my], size=mount_hole_size, drill=mount_hole_size, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_NPTH, layers=Pad.LAYERS_NPTH)) # Tab dimensions tw = 7 tt = 0.5 ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) def draw_outline(offset=0, layer='F.Fab', width=configuration['fab_line_width']): O = offset R = 1.0 if pincount == 2: poly = [ {'x': x2 + O - R, 'y': y1 - O}, {'x': x1 - O, 'y': y1 - O}, {'x': x1 - O, 'y': y2 + O}, {'x': x2 + O - R, 'y': y2 + O}, ] kicad_mod.append(PolygoneLine(polygone=poly, layer=layer, width=width)) else: # top line kicad_mod.append(Line(start=[tt+x1-O+R, y1-O], end=[x2+O-R, y1-O], layer=layer, width=width)) # bottom line kicad_mod.append(Line(start=[tt+x1-O+R, y2+O], end=[x2+O-R, y2+O], layer=layer, width=width)) # left line (including tab) poly = [ {'x': tt+x1-O, 'y': y1-O+R}, {'x': tt+x1-O, 'y': y_mid - tw/2.0 - O}, {'x': x1-O, 'y': y_mid - tw/2.0 - O}, {'x': x1-O, 'y': y_mid + tw/2.0 + O}, {'x': tt+x1-O, 'y': y_mid + tw/2.0 + O}, {'x': tt+x1-O, 'y': y2+O-R} ] kicad_mod.append(PolygoneLine(polygone=poly, width=width, layer=layer)) # top left kicad_mod.append(Arc(center=[tt+x1-O+R, y1-O+R], start=[tt+x1-O, y1-O+R], angle=90.0, layer=layer, width=width)) # bottom left kicad_mod.append(Arc(center=[tt+x1-O+R, y2+O-R], start=[tt+x1-O+R, y2+O], angle=90.0, layer=layer, width=width)) # right line kicad_mod.append(Line(start=[x2+O, y1-O+R], end=[x2+O, y2+O-R], layer=layer, width=width)) # top right kicad_mod.append(Arc(center=[x2+O-R, y1-O+R], start=[x2+O-R, y1-O], angle=90.0, layer=layer, width=width)) # bottom right kicad_mod.append(Arc(center=[x2+O-R, y2+O-R], start=[x2+O, y2+O-R], angle=90.0, layer=layer, width=width)) draw_outline() draw_outline(offset=configuration['silk_fab_offset'], layer='F.SilkS', width=configuration['silk_line_width']) # Add pin-1 marker on F.SilkS Q = 0.35 # offset L = 1.5 p1 = [ {'x': x1 - Q, 'y': y1 - Q + L}, {'x': x1 - Q, 'y': y1 - Q}, {'x': x1 - Q + L, 'y': y1 - Q}, ] kicad_mod.append(PolygoneLine(polygone=p1, layer='F.SilkS', width=configuration['silk_line_width'])) # Add pin-1 marker on F.Fab D = -0.5 - pad_size[1] / 2 M = 0.75 p1 = [ {'x': -M/2, 'y': D - M}, {'x': M/2, 'y': D - M}, {'x': 0, 'y': D}, {'x': -M/2, 'y': D - M}, ] kicad_mod.append(PolygoneLine(polygone=p1, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='left') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_NV_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "NV" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eNV.pdf' pitch = 5.0 drill = 1.7 # 1.65 +0.1/-0 -> 1.7+/-0.05 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pin_range = range(2, 5) #number of pins in each row #FP name strings part_base = "B{n:02}P-NV" #JST part number format string def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate dimensions A = (pins - 1) * pitch B = A + 5 #draw the component outline x1 = A/2 - B/2 x2 = x1 + B y2 = 4.8 y1 = y2 - 8.5 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline on F.Fab layer kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, layer='F.Fab', width=configuration['fab_line_width'])) #draw horizontal line for latch kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':(y1+1.7)},{'x':x2,'y':(y1+1.7)}],layer='F.Fab',width=0.1)) #draw pin1 mark on F.Fab kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':-1},{'x':(x1+1),'y':0}],layer='F.Fab',width=0.1)) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':1},{'x':(x1+1),'y':0}],layer='F.Fab',width=0.1)) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk outline off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off kicad_mod.append(RectLine(start=[x1,y1], end=[x2,y2], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin1 mark on silk px = x1 - 0.2 m = 0.3 marker = [{'x': px,'y': 0},{'x': px-2*m,'y': m},{'x': px-2*m,'y': -m},{'x': px,'y': 0}] kicad_mod.append(PolygoneLine(polygone=marker, layer='F.SilkS', width=configuration['silk_line_width'])) #generate tht pads (1.65mm drill with 2.35x3mm oval pads) pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill > 2*pad_copper_y_solder_length: pad_size[0] = 2*pad_copper_y_solder_length + drill if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring shape=Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: shape=Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2, 4): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_PHD_horizontal.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PHD" manufacturer = 'JST' orientation = 'H' number_of_rows = 2 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/ePHD.pdf' pitch = 2.0 row_pitch = 2.0 drill = 0.75 # 0.7 +0.1/-0 -> 0.75+/-0.05 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pin_range = range(4,18) #number of pins in each row #FP name strings part_base = "S{n}B-PHDSS" #JST part number format string def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins*number_of_rows) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 3.9 #generate the pads (row 1) size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if size[0] - drill < 2*min_annular_ring: size[0] = drill + 2*min_annular_ring if size[0] - drill > 2*pad_copper_y_solder_length: size[0] = drill + 2*pad_copper_y_solder_length if size[1] - drill < 2*min_annular_ring: size[1] = drill + 2*min_annular_ring if size[1] - drill > 2*pad_copper_y_solder_length: size[1] = drill + 2*pad_copper_y_solder_length if size[0] == size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, start=[0, row_idx*row_pitch], initial=row_idx+1, increment=2, size=size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A/2.0 - B/2.0 x2 = x1 + B y2 = row_pitch + 7 y1 = y2 - 9.5 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw fab outline measured from 3D model on JST's site # "wings" by pins are 1.0mm wide side = [ {'x': x1,'y': y1}, {'x': x1+1,'y': y1}, {'x': x1+1,'y': y1+3}, {'x': x2-1,'y': y1+3}, {'x': x2-1,'y': y1}, {'x': x2,'y': y1}, {'x': x2,'y': y2}, {'x': x1,'y': y2}, {'x': x1,'y': y1} ] kicad_mod.append(PolygoneLine(polygone=side, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if y1 < -size[1]/2.0: cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) else: cy1 = roundToBase(-size[1]/2.0-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #outline # from above, recall "wings" by pins are 1.0mm wide side = [ {'x': x1+1+2*off,'y': y1+3}, {'x': x1+1+2*off,'y': y1}, {'x': x1,'y': y1}, {'x': x1,'y': y2}, {'x': A/2.0,'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=side, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=side, x_mirror=A/2.0, width=configuration['silk_line_width'], layer='F.SilkS')) D = 0.3 L = 2.5 #add p1 marker marker = [ {'x': pitch/2.0 , 'y': y1-D+0.25}, {'x': pitch/2.0 , 'y': y1-D}, {'x': x1-D,'y': y1-D}, {'x': x1-D,'y': y1-D+L} ] kicad_mod.append(PolygoneLine(polygone=marker,width=configuration['silk_line_width'],layer='F.SilkS')) sl = 0.5 marker =[ {'x': body_edge['left']+1 , 'y': -sl}, {'x': body_edge['left']+1+(2*sl)/sqrt(2) , 'y': 0}, {'x': body_edge['left']+1 , 'y': sl} ] kicad_mod.append(PolygoneLine(polygone=marker,layer='F.Fab',width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_PHD_vertical.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PHD" manufacturer = 'JST' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/ePHD.pdf' pitch = 2.0 pin_range=range(4,18) #number of pins in each row row_pitch = 2.0 drill = 0.75 # 0.7 +0.1/-0 -> 0.75+/-0.05 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 #FP name strings part_base = "B{n}B-PHDSS" #JST part number format string def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins*number_of_rows) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 3.9 #draw the component outline x1 = A/2.0 - B/2.0 x2 = x1 + B y2 = 2 + 1.5 y1 = y2 - 5 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #wall thickness t_short = 0.75 #short side (fixed at 5mm) t_long = 0.4 #long side (A/B dimension) #draw simple outline on F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab',width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk polarity lines kicad_mod.append(RectLine(start=[x1+t_short,y1+t_long],end=[x2-t_short,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) #offset off off = configuration['silk_fab_offset'] #draw silk keying/polarity marks measured from 3D model on JST's site # from bottom (pin 2 row) of connector, notches are 1.6mm up and 0.8mm wide kicad_mod.append(Line(start=[x1-off,y2-2.4],end=[x1+t_short,y2-2.4],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2+off,y2-2.4],end=[x2-t_short,y2-2.4],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1-off,y2-1.6],end=[x1+t_short,y2-1.6],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2+off,y2-1.6],end=[x2-t_short,y2-1.6],layer='F.SilkS',width=configuration['silk_line_width'])) # from sides, inner edge of notches are 3.42mm inside and 0.94mm wide at the top (pin 1 row) and 1.50mm wide at the bottom (pin 2 row) kicad_mod.append(Line(start=[x1+3.42,y1-off],end=[x1+3.42,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1+2.48,y1-off],end=[x1+2.48,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-3.42,y1-off],end=[x2-3.42,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-2.48,y1-off],end=[x2-2.48,y1+t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1+3.42,y2+off],end=[x1+3.42,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1+1.92,y2+off],end=[x1+1.92,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-3.42,y2+off],end=[x2-3.42,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x2-1.92,y2+off],end=[x2-1.92,y2-t_long],layer='F.SilkS',width=configuration['silk_line_width'])) x1 -= off y1 -= off x2 += off y2 += off #draw silk outline kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],width=configuration['silk_line_width'],layer='F.SilkS')) #add p1 marker px = x1 - 0.2 m = 0.3 marker = [ {'x': px,'y': 0}, {'x': px-2*m,'y': m}, {'x': px-2*m,'y': -m}, {'x': px,'y': 0} ] kicad_mod.append(PolygoneLine(polygone=marker,width=configuration['silk_line_width'],layer='F.SilkS')) sl = 0.5 marker =[ {'x': body_edge['left'], 'y': sl}, {'x': body_edge['left'] + (2*sl)/sqrt(2) , 'y': 0}, {'x': body_edge['left'] , 'y': -sl} ] kicad_mod.append(PolygoneLine(polygone=marker,layer='F.Fab',width=configuration['fab_line_width'])) #generate the pads (row 1) size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if size[0] - drill < 2*min_annular_ring: size[0] = drill + 2*min_annular_ring if size[0] - drill > 2*pad_copper_y_solder_length: size[0] = drill + 2*pad_copper_y_solder_length if size[1] - drill < 2*min_annular_ring: size[1] = drill + 2*min_annular_ring if size[1] - drill > 2*pad_copper_y_solder_length: size[1] = drill + 2*pad_copper_y_solder_length if size[0] == size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, start=[0, row_idx*row_pitch], initial=row_idx+1, increment=2, size=size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_PUD_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PUD" manufacturer = 'JST' orientation = 'H' number_of_rows = 2 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/ePUD.pdf' pitch = 2.0 row_pitch = 2 drill = 0.75 # 0.7 +0.1/-0 -> 0.75+/-0.05 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 mh_drill = 1.65 mh_y = row_pitch + 7.7 pin_range = range(4,21) #number of pins in each row #FP name strings part_base = "S{n:02}B-PUDSS-1" #JST part number format string #FP description and tags def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins*number_of_rows) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 4 #generate the pads (row 1) size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if size[0] - drill < 2*min_annular_ring: size[0] = drill + 2*min_annular_ring if size[0] - drill > 2*pad_copper_y_solder_length: size[0] = drill + 2*pad_copper_y_solder_length if size[1] - drill < 2*min_annular_ring: size[1] = drill + 2*min_annular_ring if size[1] - drill > 2*pad_copper_y_solder_length: size[1] = drill + 2*pad_copper_y_solder_length if size[0] == size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, start=[0, row_idx*row_pitch], initial=row_idx+1, increment=2, size=size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A/2 - B/2 x2 = x1 + B y2 = row_pitch + 7.7 + 2.4 y1 = y2 - 12.7 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw simple outline on F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab',width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if y1 < -size[1]/2: cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) else: cy1 = roundToBase(-size[1]/2-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #outline side = [ {'x': -1,'y': y1}, {'x': x1,'y': y1}, {'x': x1,'y': y2}, {'x': A/2,'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=side, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=side, x_mirror=A/2, width=configuration['silk_line_width'], layer='F.SilkS')) #add mounting holes m1 = Pad(at=[-0.9,mh_y],layers=Pad.LAYERS_NPTH,shape=Pad.SHAPE_CIRCLE,type=Pad.TYPE_NPTH,size=mh_drill, drill=mh_drill) m2 = Pad(at=[A+0.9,mh_y],layers=Pad.LAYERS_NPTH,shape=Pad.SHAPE_CIRCLE,type=Pad.TYPE_NPTH,size=mh_drill, drill=mh_drill) kicad_mod.append(m1) kicad_mod.append(m2) D = 0.3 L = 2.5 #add p1 marker marker = [ {'x': pitch/2 , 'y': y1-D+0.25}, {'x': pitch/2 , 'y': y1-D}, {'x': x1-D,'y': y1-D}, {'x': x1-D,'y': y1-D+L} ] kicad_mod.append(PolygoneLine(polygone=marker,width=configuration['silk_line_width'],layer='F.SilkS')) sl = 1 marker =[ {'x': sl/2 , 'y': body_edge['top']}, {'x': 0 , 'y': body_edge['top']+sl/sqrt(2)}, {'x': -sl/2 , 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=marker,layer='F.Fab',width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_PUD_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PUD" manufacturer = 'JST' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/ePUD.pdf' pitch = 2.0 pin_range=range(4,21) #number of pins in each row row_pitch = 2 drill = 0.75 # 0.7 +0.1/-0 -> 0.75+/-0.05 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 mh_drill = 1.35 mh_y = -3.4 #FP name strings part_base = "B{n:02}B-PUDSS" #JST part number format string def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins*number_of_rows) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 4 #draw the component outline x1 = A/2 - B/2 x2 = x1 + B y2 = 2 + 2.4 y1 = y2 - 8.3 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw simple outline on F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab',width=configuration['fab_line_width'])) #wall thickness t t = 0.75 #draw inside tab T = A/2 + 0.5 kicad_mod.append(RectLine(start=[A/2-T/2,y1+t],end=[A/2+T/2,y1+2*t],width=configuration['silk_line_width'],layer='F.SilkS')) #,layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset off off = configuration['silk_fab_offset'] #outline side = [ {'x': A/2-T/2-t,'y': y1-off}, {'x': A/2-T/2-t,'y': y1 + 2 * t}, {'x': A/2-T/2-2*t,'y': y1 + 2 * t}, {'x': A/2-T/2-2*t,'y': y1 + t}, {'x': x1 + t,'y': y1 + t}, {'x': x1 + t,'y': y2 - t}, {'x': A/2,'y': y2 - t}, ] kicad_mod.append(PolygoneLine(polygone=side,width=configuration['silk_line_width'],layer='F.SilkS')) #, layer='F.Fab')) kicad_mod.append(PolygoneLine(polygone=side,x_mirror=A/2,width=configuration['silk_line_width'],layer='F.SilkS'))# ,layer='F.Fab')) x1 -= off y1 -= off x2 += off y2 += off #draw outline kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],width=configuration['silk_line_width'],layer='F.SilkS')) #add p1 marker px = x1 - 0.2 m = 0.3 marker = [ {'x': px,'y': 0}, {'x': px-2*m,'y': m}, {'x': px-2*m,'y': -m}, {'x': px,'y': 0} ] kicad_mod.append(PolygoneLine(polygone=marker,width=configuration['silk_line_width'],layer='F.SilkS')) sl = 1 marker =[ {'x': body_edge['left'], 'y': sl/2}, {'x': body_edge['left']+sl/sqrt(2) , 'y': 0}, {'x': body_edge['left'] , 'y': -sl/2} ] kicad_mod.append(PolygoneLine(polygone=marker,layer='F.Fab',width=configuration['fab_line_width'])) #generate the pads (row 1) size = [pitch - pad_to_pad_clearance, row_pitch - pad_to_pad_clearance] if size[0] - drill < 2*min_annular_ring: size[0] = drill + 2*min_annular_ring if size[0] - drill > 2*pad_copper_y_solder_length: size[0] = drill + 2*pad_copper_y_solder_length if size[1] - drill < 2*min_annular_ring: size[1] = drill + 2*min_annular_ring if size[1] - drill > 2*pad_copper_y_solder_length: size[1] = drill + 2*pad_copper_y_solder_length if size[0] == size[1]: pad_shape = Pad.SHAPE_CIRCLE else: pad_shape = Pad.SHAPE_OVAL optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, start=[0, row_idx*row_pitch], initial=row_idx+1, increment=2, size=size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_VH_tht_side-stabilizer.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "VH" manufacturer = 'JST' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eVH.pdf' pitch = 3.96 pin_range = range(2, 8) #number of pins in each row drill = 1.7 # 1.65 +0.1/-0.0 -> 1.7+/-0.05 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 #FP name strings part_base = "S{n}P-VH" #JST part number format string #FP description and tags # DISCLAIMER: This generator uses many magic numbers for the silk screen details. These might break if some parameters are changed. def generate_one_footprint(pins, configuration): silk_pad_clearance = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 mpn = part_base.format(n=pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 3.9 #coordinate locations # y1 x1 x3 x4 x2 # y2 | | | | # y3 | |1||2||3||4||5||6||7| | # y4 |_| |__| # | | # y5 |__________________| # y6 || || || || || || || #generate pads pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*pad_copper_y_solder_length: pad_size[0] = drill + 2*pad_copper_y_solder_length shape=Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: shape=Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A/2 - B/2 x2 = x1 + B x3 = -0.9 x4 = pitch * (pins - 1) + 0.9 y6 = 13.4 y4 = y6 - 7.7 y1 = y4 - 7.7 y2 = y1 + 2 y3 = y1 + 4.5 y5 = y3 + 9.4 body_edge={'left':x1, 'right':x2, 'top':y4, 'bottom':y5} #draw shroud outline on F.Fab layer kicad_mod.append(RectLine(start=[x3,y3],end=[x4,y5], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x4-0.2,'y':y3},{'x':x4-0.2,'y':y1},{'x':x2,'y':y1},{'x':x2,'y':y4},{'x':x4,'y':y4}], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x3,'y':y4},{'x':x1,'y':y4},{'x':x1,'y':y1},{'x':x3+0.2,'y':y1},{'x':x3+0.2,'y':y3}], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y6+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw pin outlines and plastic between pins on F.Fab (pin width is 1.4mm, so 0.7mm is half the pin width) for pin in range(pins): kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 0.7,'y':y5},{'x':pin * pitch - 0.7,'y':y6},{'x':pin * pitch + 0.7,'y':y6},{'x':pin * pitch + 0.7,'y':y5}], layer='F.Fab', width=configuration['fab_line_width'])) if pin < (pins - 1): kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch + 1.38,'y':y3},{'x':pin * pitch + 1.38,'y':y2},{'x':pin * pitch + 2.58,'y':y2},{'x':pin * pitch + 2.58,'y':y3}], layer='F.Fab', width=configuration['fab_line_width'])) #draw pin1 mark on F.Fab kicad_mod.append(PolygoneLine(polygone=[{'x':-0.8,'y':y3},{'x':0,'y':y3+0.8},{'x':0.8,'y':y3}], layer='F.Fab', width=configuration['fab_line_width'])) #draw silk outlines off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 -= off x3 -= off y3 -= off x4 += off y4 += off y5 += off y6 += off p1s_x = pad_size[0]/2 + silk_pad_clearance p1s_y = pad_size[1]/2 + silk_pad_clearance #silk around shroud; silk around stabilizers; silk long shroud between pin and shroud for first and last pins #note that half of pin width is 0.7mm, so adding 0.12mm silk offset gives 0.82mm about pin center; 0.44 is double silk offset in caeses where 'off' is in the wrong direction kicad_mod.append(PolygoneLine(polygone=[{'x':x3,'y':y4},{'x':x3,'y':y5},{'x':-0.82,'y':y5}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x4-0.44,'y':-1.6},{'x':x4-0.44,'y':y1},{'x':x2,'y':y1},{'x':x2,'y':y4},{'x':x4,'y':y4}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x4-0.44,'y':y3},{'x':x4-0.44,'y':1.6}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x3,'y':y4},{'x':x1,'y':y4},{'x':x1,'y':y1},{'x':x3+0.44,'y':y1},{'x':x3+0.44,'y':-p1s_y}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x3+0.44,'y':1.7},{'x':x3+0.44,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':(pins - 1) * pitch + 0.82,'y':y5},{'x':x4,'y':y5},{'x':x4,'y':y4}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':-0.58,'y':y3},{'x':1.26,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 1.26,'y':y3},{'x':pin * pitch + 0.58,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) #per-pin silk #pin silk for pin in range(pins): kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 0.82,'y':y5},{'x':pin * pitch - 0.82,'y':y6},{'x':pin * pitch + 0.82,'y':y6},{'x':pin * pitch + 0.82,'y':y5}], layer='F.SilkS', width=configuration['silk_line_width'])) #silk around plastic between pins 1 and 2 (since pin 1 is rectangular, it seends to be handled a bit differently to meet ~0.2mm pin-silk clearance) if pin == 0: kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch + 1.26,'y':y3},{'x':pin * pitch + 1.26,'y':1.7}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[ {'x':pin * pitch + pad_size[0]/2 + silk_pad_clearance,'y':y2}, {'x':(pin+1) * pitch - pad_size[0]/2 - silk_pad_clearance,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch + 2.7,'y':1},{'x':pin * pitch + 2.7,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) #silk around plastic between other pins; silk along shroud between pin and shroud for other pins if (pin > 0) and (pin < (pins - 1)): kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch + 1.26,'y':y3},{'x':pin * pitch + 1.26,'y':1}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[ {'x':pin * pitch + pad_size[0]/2 + silk_pad_clearance,'y':y2}, {'x':(pin+1) * pitch - pad_size[0]/2 - silk_pad_clearance,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch + 2.7,'y':1},{'x':pin * pitch + 2.7,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 1.26,'y':y3},{'x':pin * pitch + 1.26,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) #silk between pins at locking end of shroud if (pin > 0) and (pin < pins): kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 3.14,'y':y5},{'x':pin * pitch - 0.82,'y':y5}],layer='F.SilkS')) #add pin1 marker on F.FilkS (magic numbers intended to hit ~0.3mm copper-silk clearance) kicad_mod.append(PolygoneLine(polygone=[{'x':0,'y':-p1s_y},{'x':-p1s_x,'y':-p1s_y},{'x':-p1s_x,'y':0}], layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_VH_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "VH" manufacturer = 'JST' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eVH.pdf' pitch = 3.96 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 drill = 1.7 # 1.65 +0.1/-0.0 -> 1.7 +/-0.05 pin_range = range(2, 11) #number of pins in each row #FP name strings part_base = "B{n}PS-VH" #JST part number format string #FP description and tags def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins - 1) * pitch B = A + 3.9 #coordinate locations # x1 x3 x4 x2 # 1 2 3 4 5 6 7 # y1 _______________________ # y2 |_| |__| # | | # y3 |__________________| # y4 || || || || || || || #generate pads pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*pad_copper_y_solder_length: pad_size[0] = drill + 2*pad_copper_y_solder_length shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: shape=Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the component outline x1 = A/2 - B/2 x2 = x1 + B x3 = -0.9 x4 = pitch * (pins - 1) + 0.9 y1 = 14.9 - 7.7 - 3.2 y2 = y1 + 3.2 y3 = y1 + 9.4 y4 = 14.9 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y4} #draw shroud outline on F.Fab layer kicad_mod.append(RectLine(start=[x3,y1],end=[x4,y3],layer='F.Fab',width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x4,'y':y1},{'x':x2,'y':y1},{'x':x2,'y':y2},{'x':x4,'y':y2}], layer='F.Fab',width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x3,'y':y2},{'x':x1,'y':y2},{'x':x1,'y':y1},{'x':x3,'y':y1}], layer='F.Fab',width=configuration['fab_line_width'])) #draw pin1 mark on F.Fab kicad_mod.append(PolygoneLine(polygone=[{'x':-0.8,'y':y1},{'x':0,'y':y1+0.8},{'x':0.8,'y':y1}], layer='F.Fab',width=configuration['fab_line_width'])) #draw pin outlines on F.Fab (pin width is 1.4mm, so 0.7mm is half the pin width) for pin in range(pins): kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 0.7,'y':y1}, {'x':pin * pitch - 0.7,'y':0}, {'x':pin * pitch + 0.7,'y':0}, {'x':pin * pitch + 0.7,'y':y1}], layer='F.Fab',width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 0.7,'y':y3}, {'x':pin * pitch - 0.7,'y':y4}, {'x':pin * pitch + 0.7,'y':y4}, {'x':pin * pitch + 0.7,'y':y3}], layer='F.Fab',width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(-pad_size[1]/2-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y4+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk outlines off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off x3 -= off y3 += off x4 += off y4 += off kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x4,'y':y2}, {'x':x4,'y':y3}, {'x':x3,'y':y3}, {'x':x3,'y':y2}, {'x':x1,'y':y2}, {'x':x1,'y':y1}], layer='F.SilkS', width=configuration['silk_line_width'])) #pin silk (half of pin width is 0.7mm, so adding 0.12mm silk offset gives 0.82mm about pin center) for pin in range(pins): kicad_mod.append(PolygoneLine(polygone=[{'x':pin * pitch - 0.82,'y':y3}, {'x':pin * pitch - 0.82,'y':y4}, {'x':pin * pitch + 0.82,'y':y4}, {'x':pin * pitch + 0.82,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin1 marker on F.FilkS p1_y1 = -pad_size[1]/2 - configuration['silk_pad_clearance'] - configuration['silk_line_width']/2 p1_x1 = -pad_size[0]/2 - configuration['silk_pad_clearance'] - configuration['silk_line_width']/2 kicad_mod.append(PolygoneLine(polygone=[{'x':0,'y':p1_y1},{'x':p1_x1,'y':p1_y1},{'x':p1_x1,'y':0}], layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_VH_tht_top-shrouded.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "VH" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eVH.pdf' pitch = 3.96 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 drill = 1.7 # 1.65 +0.1/-0.0 -> 1.7+/-0.05 mh_drill = 1.45 mh_at = [-1.5, -3.4] pin_range = range(2, 11) #number of pins in each row #FP name strings part_base = "B{n:d}P-VH-FB-B" #JST part number format string def generate_one_footprint(pins, configuration): mpn = part_base.format(n=pins) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s}, shrouded ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate dimensions A = (pins - 1) * pitch B = A + 5.84 #coordinate locations (latch is not drawn but is 2.3mm above y5 and width varies) # x1 x5 x3 x4 x6 x2 # y1 ______ ______ # y3 | O |_____________| | # y5 | ___________________ | # | | 1 2 3 4 5 6 7 8 | | # y4 | |__________________| | # y2 |_______________________| #draw the component outline x1 = A/2 - B/2 x2 = x1 + B x3 = x1 + 2.9 x4 = x2 - 2.9 x5 = -2 x6 = pitch * (pins - 1) + 2 y2 = 5.2 y1 = y2 - 9.7 y3 = y1 + 1.2 y4 = 4.3 y5 = y4 - 6.4 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw outline on F.Fab layer kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x3,'y':y1}, {'x':x3,'y':y3}, {'x':x4,'y':y3}, {'x':x4,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x1,'y':y2}], layer='F.Fab',width=configuration['fab_line_width'])) #draw rectangle on F.Fab for shroud walls kicad_mod.append(RectLine(start=[x5,y4],end=[x6,y5],layer='F.Fab',width=configuration['fab_line_width'])) #draw pin1 mark on F.Fab kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':-1},{'x':(x1+1),'y':0}],layer='F.Fab',width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':1},{'x':(x1+1),'y':0}],layer='F.Fab',width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk outline off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off x3 += off y3 -= off x4 -= off kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x3,'y':y1}, {'x':x3,'y':y3}, {'x':x4,'y':y3}, {'x':x4,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x1,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin1 mark on silk px = x1 - 0.2 m = 0.3 marker = [{'x': px,'y': 0},{'x': px-2*m,'y': m},{'x': px-2*m,'y': -m},{'x': px,'y': 0}] kicad_mod.append(PolygoneLine(polygone=marker,layer="F.SilkS", width=configuration['silk_line_width'])) #generate tht pads (1.65mm drill with 2.35x3mm oval pads) pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*pad_copper_y_solder_length: pad_size[0] = drill + 2*pad_copper_y_solder_length shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: shape=Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #generate mounting post post = Pad(at=mh_at, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mh_drill, drill=mh_drill, layers=Pad.LAYERS_NPTH) kicad_mod.append(post) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=2.5) ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pin_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_eh_tht_side.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "EH" manufacturer = 'JST' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eEH.pdf' pitch = 2.50 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 def generate_one_footprint(pincount, configuration): mpn = "S{pincount}B-EH".format(pincount=pincount) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if pincount == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring # create pads # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) A = (pincount - 1) * pitch B = A + 5.0 x1 = -2.5 y1 = -6.7 x2 = x1 + B y21 = y1 + 6 y2 = 1.5 x11 = x1+1 x21 = x2-1 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline around the footprint # kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, layer='F.Fab', width=configuration['fab_line_width'])) fab_outline=[ {'x': x11, 'y': y21}, {'x': x11, 'y': y2}, {'x': x1, 'y': y2}, {'x': x1, 'y': y1}, {'x': x2, 'y': y1}, {'x': x2, 'y': y2}, {'x': x21, 'y': y2}, {'x': x21, 'y': y21}, {'x': x11, 'y': y21} ] kicad_mod.append(PolygoneLine(polygone=fab_outline, layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ########################### SilkS ################################# #line offset off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off T = 1 + 2*configuration['silk_fab_offset'] y3 = y21 + off kicad_mod.append(PolygoneLine(polygone=[{'x':x1+T,'y':y3}, {'x':x1+T,'y':y2}, {'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x2-T,'y':y2}, {'x':x2-T,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y1+T}, {'x':x1+T,'y':y1+T}, {'x':x1+T,'y':y3}, {'x':x1,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x2,'y':y1+T}, {'x':x2-T,'y':y1+T}, {'x':x2-T,'y':y3}, {'x':x2,'y':y3}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pictures of pins #pin-width w #pin-length l w = 0.32 l = 3.5 py = y3-1 kicad_mod.append(Line(start={'x':x1+T,'y':py},end={'x':x2-T,'y':py}, layer='F.SilkS', width=configuration['silk_line_width'])) # kicad_mod.append(Line(start={'x':x1+T,'y':py+1},end={'x':x2-T,'y':py+1}, layer='F.SilkS', width=configuration['silk_line_width'])) pcs_x = pad_size[0]/2 + configuration['silk_pad_clearance'] + configuration['silk_line_width'] for p in range(pincount): px = p * pitch kicad_mod.append(PolygoneLine(polygone=[{'x': px,'y': py}, {'x': px-w,'y': py}, {'x': px-w,'y': py-l+0.25*w}, {'x': px,'y': py-l}, {'x': px+w,'y': py-l+0.25*w}, {'x': px+w,'y': py}, {'x': px,'y': py}], layer='F.SilkS', width=configuration['silk_line_width'])) if p < pincount-1: kicad_mod.append(Line(start=[px + pcs_x, y3], end=[px + pitch - pcs_x, y3], layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Pin 1 marker ############################## xm = 0 ym = 1.5 m = 0.3 pin = [{'x':xm,'y':ym}, {'x':xm - m,'y':ym + 2 * m}, {'x':xm + m,'y':ym + 2 * m}, {'x':xm,'y':ym}] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 1 pin = [ {'x':xm-sl/2,'y':y21}, {'x':xm,'y':y21-sl/sqrt(2)}, {'x':xm+sl/2,'y':y21} ] kicad_mod.append(PolygoneLine(polygone=pin,layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2, 16): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_eh_tht_top.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "EH" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eEH.pdf' pitch = 2.50 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 def generate_one_footprint(pincount, configuration): mpn = "B{pincount}B-EH-A".format(pincount=pincount) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pincount - 1) * pitch B = A + 5.0 # set general values if pincount == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring # create pads # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) x1 = -2.5 y1 = -1.6 x2 = x1 + B y2 = y1 + 3.8 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the main outline on F.Fab layer kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #line offset off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off #draw the main outline around the footprint kicad_mod.append(RectLine(start={'x':x1,'y':y1},end={'x':x2,'y':y2}, layer='F.SilkS', width=configuration['silk_line_width'])) T = 0.5 #add top line kicad_mod.append(PolygoneLine(polygone=[{'x': x1,'y': 0}, {'x': x1 + T,'y': 0}, {'x': x1 + T,'y': y1 + T}, {'x': x2 - T,'y': y1 + T}, {'x': x2 - T,'y': 0}, {'x': x2,'y':0}], layer='F.SilkS', width=configuration['silk_line_width'])) #add bottom line (left) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':y2-3*T}, {'x':x1+2*T,'y':y2-3*T}, {'x':x1+2*T,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) #add bottom line (right) kicad_mod.append(PolygoneLine(polygone=[{'x':x2,'y':y2-3*T}, {'x':x2-2*T,'y':y2-3*T}, {'x':x2-2*T,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 marker D = 0.3 L = 2.5 pin = [ {'x': x1-D,'y': y2+D-L}, {'x': x1-D,'y': y2+D}, {'x': x1-D+L,'y': y2+D}, ] kicad_mod.append(PolygoneLine(polygone=pin)) kicad_mod.append(PolygoneLine(polygone=pin, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2, 16): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_ph_tht_side.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PH" manufacturer = 'JST' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/ePH.pdf' silk_pin1_marker_type = 2 fab_pin1_marker_type = 3 pitch = 2.00 #pad_size=[1.2, 1.7] drill_size = 0.75 #Datasheet: 0.7 +0.1/-0.0 => It might be better to assume 0.75 +/-0.05mm pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 # Connector Parameters x_min = -1.95 y_max = 6.25 y_min = y_max-6-1.6 y_main_min = y_max - 6 body_back_protrusion_width=0.7 def generate_one_footprint(pincount, configuration): silk_x_min = x_min - configuration['silk_fab_offset'] silk_y_min = y_min - configuration['silk_fab_offset'] silk_y_main_min = y_main_min - configuration['silk_fab_offset'] silk_y_max = y_max + configuration['silk_fab_offset'] x_mid = (pincount-1)*pitch/2.0 x_max = (pincount-1)*pitch + 1.95 silk_x_max = x_max + configuration['silk_fab_offset'] pad_size = [pitch - pad_to_pad_clearance, drill_size + 2*pad_copper_y_solder_length] if pad_size[0] - drill_size < 2*min_annular_ring: pad_size[0] = drill_size + 2*min_annular_ring # Through-hole type shrouded header, Side entry type mpn = "S{n}B-PH-K".format(n=pincount) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # create Silkscreen tmp_x1=x_min+body_back_protrusion_width+configuration['silk_fab_offset'] tmp_x2=x_max-body_back_protrusion_width-configuration['silk_fab_offset'] pad_silk_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 poly_silk_outline= [ {'x':-pad_size[0]/2.0-pad_silk_offset, 'y':silk_y_main_min}, {'x':tmp_x1, 'y':silk_y_main_min}, {'x':tmp_x1, 'y':silk_y_min}, {'x':silk_x_min, 'y':silk_y_min}, {'x':silk_x_min, 'y':silk_y_max}, {'x':silk_x_max, 'y':silk_y_max}, {'x':silk_x_max, 'y':silk_y_min}, {'x':tmp_x2, 'y':silk_y_min}, {'x':tmp_x2, 'y':silk_y_main_min}, {'x':(pincount-1)*pitch+pad_size[0]/2.0+pad_silk_offset, 'y':silk_y_main_min} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_outline, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['allow_silk_below_part'] == 'tht' or configuration['allow_silk_below_part'] == 'both': poly_big_cutout=[{'x':0.5, 'y':silk_y_max} ,{'x':0.5, 'y':2} ,{'x':x_max-2.45, 'y':2} ,{'x':x_max-2.45, 'y':silk_y_max}] kicad_mod.append(PolygoneLine(polygone=poly_big_cutout, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_min, silk_y_main_min], end=[tmp_x1, silk_y_main_min], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_max, silk_y_main_min], end=[tmp_x2, silk_y_main_min], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(RectLine(start=[-1.3, 2.5], end=[-0.3, 4.1], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(RectLine(start=[(pincount-1)*pitch+1.3, 2.5], end=[(pincount-1)*pitch+0.3, 4.1], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-0.3, 4.1], end=[-0.3, silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-0.8, 4.1], end=[-0.8, silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################ part_x_min = x_min part_x_max = x_max part_y_min = y_min part_y_max = y_max cx1 = roundToBase(part_x_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(part_y_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(part_x_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(part_y_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ########################### Fab Outline ################################ tmp_x1=x_min+body_back_protrusion_width tmp_x2=x_max-body_back_protrusion_width poly_fab_outline= [ {'x':tmp_x1, 'y':y_main_min}, {'x':tmp_x1, 'y':y_min}, {'x':x_min, 'y':y_min}, {'x':x_min, 'y':y_max}, {'x':x_max, 'y':y_max}, {'x':x_max, 'y':y_min}, {'x':tmp_x2, 'y':y_min}, {'x':tmp_x2, 'y':y_main_min}, {'x':tmp_x1, 'y':y_main_min} ] kicad_mod.append(PolygoneLine(polygone=poly_fab_outline, layer='F.Fab', width=configuration['fab_line_width'])) ############################# Pads ################################## # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill_size, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) ########################### Pin 1 marker ################################ poly_pin1_marker = [ {'x':0, 'y':-1.2}, {'x':-0.4, 'y':-1.6}, {'x':0.4, 'y':-1.6}, {'x':0, 'y':-1.2} ] if silk_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if silk_pin1_marker_type == 2: silk_pin1_marker_t2_x = -pad_size[0]/2.0-pad_silk_offset kicad_mod.append(Line(start=[silk_pin1_marker_t2_x, silk_y_main_min], end=[silk_pin1_marker_t2_x, -pad_size[1]/2.0-configuration['silk_pad_clearance']],layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: poly_pin1_marker_type2 = [ {'x':-0.75, 'y':y_main_min}, {'x':0, 'y':y_main_min+0.75}, {'x':0.75, 'y':y_main_min} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 3: fab_pin1_marker_t3_y = pad_size[1]/2.0 poly_pin1_marker_type2 = [ {'x':0, 'y':fab_pin1_marker_t3_y}, {'x':-0.5, 'y':fab_pin1_marker_t3_y+0.5}, {'x':0.5, 'y':fab_pin1_marker_t3_y+0.5}, {'x':0, 'y':fab_pin1_marker_t3_y} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### text_center_y = 2.5 body_edge={'left':part_x_min, 'right':part_x_max, 'top':part_y_min, 'bottom':part_y_max} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2,17): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_ph_tht_top.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PH" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/ePH.pdf' fab_pin1_marker_type = 1 pin1_marker_offset = 0.3 pin1_marker_linelen = 1.25 drill_size = 0.75 #Datasheet: 0.7 +0.1/-0.0 => It might be better to assume 0.75 +/-0.05mm pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pitch = 2.00 # Connector Parameters x_min = -1.95 y_min = -1.7 y_max = y_min + 4.5 def generate_one_footprint(pincount, configuration): silk_x_min = x_min - configuration['silk_fab_offset'] silk_y_min = y_min - configuration['silk_fab_offset'] silk_y_max = y_max + configuration['silk_fab_offset'] x_mid = (pincount-1)*pitch/2.0 x_max = (pincount-1)*pitch + 1.95 silk_x_max = x_max + configuration['silk_fab_offset'] # Through-hole type shrouded header, Top entry type mpn = "B{n}B-PH-K".format(n=pincount) #JST part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # create Silkscreen kicad_mod.append(RectLine(start=[silk_x_min,silk_y_min], end=[silk_x_max,silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) silk_inner_left=-1.45 silk_inner_right=x_max-0.5 poly_silk_p1_protrusion=[ {'x':-0.3, 'y':silk_y_min}, {'x':-0.3, 'y':silk_y_min-0.2}, {'x':-0.6, 'y':silk_y_min-0.2}, {'x':-0.6, 'y':silk_y_min} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_p1_protrusion, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[-0.3, silk_y_min-0.1], end=[-0.6, silk_y_min-0.1], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['allow_silk_below_part'] == 'tht' or configuration['allow_silk_below_part'] == 'both': poly_silk_inner_outline = [ {'x':0.5, 'y':silk_y_min}, {'x':0.5, 'y':-1.2}, {'x':silk_inner_left, 'y':-1.2}, {'x':silk_inner_left, 'y':2.3}, {'x':silk_inner_right, 'y':2.3}, {'x':silk_inner_right, 'y':-1.2}, {'x':x_max-2.45, 'y':-1.2}, {'x':x_max-2.45, 'y':silk_y_min} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_inner_outline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_min, -0.5], end=[silk_inner_left, -0.5], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_min, 0.8], end=[silk_inner_left, 0.8], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_max, -0.5], end=[silk_inner_right, -0.5], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_x_max, 0.8], end=[silk_inner_right, 0.8], layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(0, pincount-1): middle_x = 1+i*2 start_x = middle_x-0.1 end_x = middle_x+0.1 poly_silk_inner_protrusion=[ {'x':start_x, 'y':2.3}, {'x':start_x, 'y':1.8}, {'x':end_x, 'y':1.8}, {'x':end_x, 'y':2.3} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_inner_protrusion, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[middle_x, 2.3], end=[middle_x, 1.8], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### Pin 1 marker ################################ poly_pin1_marker = [ {'x':silk_x_min-pin1_marker_offset+pin1_marker_linelen, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset+pin1_marker_linelen} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: poly_pin1_marker_type2 = [ {'x':-1, 'y':y_min}, {'x':0, 'y':y_min+1}, {'x':1, 'y':y_min} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) ########################## Fab Outline ############################### kicad_mod.append(RectLine(start=[x_min,y_min], end=[x_max,y_max], layer='F.Fab', width=configuration['fab_line_width'])) ############################# CrtYd ################################## part_x_min = x_min part_x_max = x_max part_y_min = y_min part_y_max = y_max cx1 = roundToBase(part_x_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(part_y_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(part_x_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(part_y_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ############################# Pads ################################## pad_size = [pitch - pad_to_pad_clearance, drill_size + 2*pad_copper_y_solder_length] if pad_size[0] - drill_size < 2*min_annular_ring: pad_size[0] = drill_size + 2*min_annular_ring # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill_size, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### text_center_y = 1.5 body_edge={'left':part_x_min, 'right':part_x_max, 'top':part_y_min, 'bottom':part_y_max} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2,17): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_vh_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "VH" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eVH.pdf' pitch = 3.96 drill = 1.7 # 1.65 +0.1/-0.0 -> 1.7 +/-0.05 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 #FP name strings part_base = "B{n:d}P{n_total:s}-{suffix:s}" def generate_one_footprint(pins, series_params, configuration): #calculate dimensions A = (pins - 1) * pitch B = A + 3.9 post_omitted = True if len(series_params) == 4 else False pins_used = pins - len(series_params[3]) if post_omitted else pins # if removed pins are a fixed pattern (every 2 pins, every 3 pins, etc.), # then we can determine an effective pitch # if all pins are loaded or removed pins are disorderly use the default pitch pitch_effective = pitch if post_omitted: if ((pins - 1) % (pins_used - 1)) == 0: pitch_effective = ((pins - 1) / (pins_used - 1)) * pitch #generate name mpn = part_base.format(n = pins_used, n_total = str(pins) if post_omitted else '', suffix=series_params[1]) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_used, mounting_pad = "", pitch=pitch_effective, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series_params[2], mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #coordinate locations # x1 x3 x4 x2 # y3 ____________________ # y1 __|____________________|__ # | 1 2 3 4 5 6 7 8 | # y2 |________________________| #draw the component outline x1 = A/2 - B/2 x2 = x1 + B y2 = 4.8 y1 = y2 - 6.8 y3 = y1 - 1.7 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw outline on F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) #draw rectangle on F.Fab for latch x3 = -0.75 x4 = pitch * (pins - 1) + 0.75 kicad_mod.append(PolygoneLine(polygone=[{'x':x3,'y':y1},{'x':x3,'y':y3},{'x':x4,'y':y3},{'x':x4,'y':y1}], layer='F.Fab', width=configuration['fab_line_width'])) #draw pin1 mark on F.Fab kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':-1},{'x':(x1+1),'y':0}], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[{'x':x1,'y':1},{'x':(x1+1),'y':0}], layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y3-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw silk outline off = configuration['silk_fab_offset'] x1 -= off y1 -= off x2 += off y2 += off x3 -= off y3 -= off x4 += off kicad_mod.append(PolygoneLine(polygone=[ {'x':x1,'y':y2}, {'x':x1,'y':y1}, {'x':x3,'y':y1}, {'x':x3,'y':y3}, {'x':x4,'y':y3}, {'x':x4,'y':y1}, {'x':x2,'y':y1}, {'x':x2,'y':y2}, {'x':x1,'y':y2}], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin1 mark on silk px = x1 - 0.2 m = 0.3 marker = [{'x': px,'y': 0},{'x': px-2*m,'y': m},{'x': px-2*m,'y': -m},{'x': px,'y': 0}] kicad_mod.append(PolygoneLine(polygone=marker, layer='F.SilkS', width=configuration['silk_line_width'])) pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*pad_copper_y_solder_length: pad_size[0] = drill + 2*pad_copper_y_solder_length shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: shape=Pad.SHAPE_CIRCLE optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT optional_pad_params['radius_ratio'] = 0.25 optional_pad_params['maximum_radius'] = 0.25 exclude_pin_list = series_params[3] if post_omitted else [] if post_omitted: if pins > 3 and len(series_params[3]) == 1: for pin in range(1, pins + 1): if pin != series_params[3][0]: #shape = optional_pad_params['tht_pad1_shape'] if pin == 1 else shape kicad_mod.append(Pad( number=pin, at=[(pin - 1) * pitch_effective, 0], type=Pad.TYPE_THT, shape=optional_pad_params['tht_pad1_shape'] if pin == 1 else shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) else: for pin in range(1, pins_used + 1): kicad_mod.append(Pad( number=pin, at=[(pin - 1) * pitch_effective, 0], type=Pad.TYPE_THT, shape=optional_pad_params['tht_pad1_shape'] if pin == 1 else shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) else: kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible #tuple argument meaning: [start,end] list for range of pin counts, MPN suffix, material, optional list of missing pins #the first two tuples generate the fully-stuffed parts while the last tuple makes a 3-pin part with pin 2 missing #here are examples from page 4 of the datasheet (this can generate non-contiguous pin numbers so be careful!): #1) B6P7-VH: ([7,8], series, series, [6]) #2) B6P7-VH-L: ([7,8], series + "-L", series, [2]) #3) 1. B4P7-VH: ([7,8], series, series, [2,4,6]) #3) 2. B3P7-VH: ([7,8], series, series, [2,3,5,6]) #3) 3. B3P9-VH: ([9,10], series, series, [2,3,4,6,7,8]) #for series_params in [([7,8], series, series, [6]), ([7,8], series + "-L", series, [2]), ([7,8], series, series, [2,4,6]), ([7,8], series, series, [2,3,5,6]), ([9,10], series, series, [2,3,4,6,7,8])]: for series_params in [([2,11], series, series), ([2,12], series + "-B", series + " PBT"), ([3,4], series, series, [2])]: for pincount in range(series_params[0][0], series_params[0][1]): generate_one_footprint(pincount, series_params, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_xh_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "XH" manufacturer = 'JST' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eXH.pdf' pitch = 2.50 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 #FP name strings part_base = "S{n}B-XH-{variant:s}" #JST part number format string fab_pin1_marker_type = 2 fab_first_marker_w = 1.25 fab_first_marker_h = 1 #FP description and tags variant_params = { 'A':{ 'V': 9.2, 'pin_range': range(2,17) }, 'A-1':{ 'V': 7.6, 'pin_range': range(2,16) } } def generate_one_footprint(pins, variant, configuration): V=variant_params[variant]['V'] #calculate fp dimensions A = (pins - 1) * pitch B = A + 4.9 #Thickness of connector T = 11.5 #corners x1 = -2.45 x2 = x1 + B x_mid = (x1 + x2) / 2 y2 = V y1= y2 - T #y at which the plastic tabs end y3 = y2 - 7 #generate the name mpn = part_base.format(n=pins, variant=variant) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if pins == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring #generate the pads ############################# Pads ################################## # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the courtyard cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #offset the outline around the connector off = configuration['silk_fab_offset'] xo1 = x1 - off yo1 = y1 - off xo2 = x2 + off yo2 = y2 + off #thickness of the notches notch = 1.5 #wall thickness of the outline wall = 1.2 #draw the outline of the connector outline = [ {'x': x_mid,'y': yo2}, {'x': xo1,'y': yo2}, {'x': xo1,'y': yo1}, {'x': xo1+wall+2*off,'y': yo1}, {'x': xo1+wall+2*off,'y': y3 - off}, {'x': A/2,'y': y3 - off}, #{'x': -1.1,'y': y3 + off} ] if variant == 'A-1': outline = outline[:-1] kicad_mod.append(PolygoneLine(polygone=outline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline, x_mirror=x_mid, layer='F.SilkS', width=configuration['silk_line_width'])) outline = [ {'x': x_mid,'y': y2}, {'x': x1,'y': y2}, {'x': x1,'y': y1}, {'x': x1+wall,'y': y1}, {'x': x1+wall,'y': y3}, {'x': A/2,'y': y3}, #{'x': -1.1,'y': y3 + off} ] kicad_mod.append(PolygoneLine(polygone=outline, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline, x_mirror=x_mid, layer='F.Fab', width=configuration['fab_line_width'])) #draw the pinsss for i in range(pins): x = i * pitch w = 0.25 kicad_mod.append(RectLine(start=[x-w,y3+1], end=[x+w,y2-0.5], layer='F.SilkS', width=configuration['silk_line_width'])) #add pin-1 designator px = 0 py = -1.5 m = 0.3 pin1 = [ {'x': px,'y': py}, {'x': px-m,'y': py-2*m}, {'x': px+m,'y': py-2*m}, {'x': px,'y': py}, ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: fab_marker_left = -fab_first_marker_w/2.0 fab_marker_bottom = y3 - fab_first_marker_h poly_fab_marker = [ {'x':fab_marker_left, 'y':y3}, {'x':0, 'y':fab_marker_bottom}, {'x':fab_marker_left + fab_first_marker_w, 'y':y3} ] kicad_mod.append(PolygoneLine(polygone=poly_fab_marker, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### text_center_y = 'center' body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pincount in variant_params[variant]['pin_range']: generate_one_footprint(pincount, variant, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_xh_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from itertools import chain series = "XH" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eXH.pdf' pitch = 2.50 pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 #FP name strings part_base = "B{n}B-XH-{variant:s}" #JST part number format string variant_params = { 'A':{ 'boss': False, 'back_protrusion': False, 'pin_range': chain(range(2,17), [20]) }, 'AM':{ 'boss': True, 'back_protrusion': False, 'pin_range': chain(range(1,11), [12]) } } fab_first_marker_w = 1.25 pin1_marker_linelen = 1.25 fab_first_marker_h = 1 fab_pin1_marker_type = 2 pin1_marker_offset = 0.3 #FP description and tags def generate_one_footprint(pins, variant, configuration): #calculate fp dimensions boss = variant_params[variant]['boss'] A = (pins - 1) * pitch B = A + 4.9 #connector thickness T = 5.75 #corners x1 = -2.45 x2 = x1 + B x_mid = (x1 + x2) / 2 y1 = -2.35 y2 = y1 + T #generate the name mpn = part_base.format(n=pins, variant=variant) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s}{:s} ({:s}), generated with kicad-footprint-generator".format( series, mpn, ', with boss' if boss else '', datasheet)) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) if boss: tags += " boss" #set the FP tags kicad_mod.setTags(tags) #draw simple outline on F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab', width=configuration['fab_line_width'])) # set general values #kicad_mod.append(Text(type='reference', text='REF**', at=[x_mid,-3.5], layer='F.SilkS')) if pins == 2: drill = 1.0 else: drill = 0.95 pad_size = [pitch - pad_to_pad_clearance, drill + 2*pad_copper_y_solder_length] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring #generate the pads ############################# Pads ################################## # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pins, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) if boss: if pins == 1: boss_y = 4.35 boss_x = 0 boss_drill = 1.75 kicad_mod.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) else: boss_y = 2 boss_x = -1.6 boss_drill = 1.2 kicad_mod.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) if boss and pins == 1: boss_size_1pin = 1.5 off = configuration['silk_fab_offset'] x_boss_fab_off = boss_size_1pin/2 + off x_boss_pad_off = boss_drill/2 + configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] x_boss = x_boss_fab_off if x_boss_pad_off > x_boss: x_boss=x_boss_pad_off out_silk = PolygoneLine(polygone=[ {'x': -x_boss, 'y':boss_y}, {'x': -x_boss, 'y':y2+off}, {'x': x1-off, 'y':y2+off}, {'x': x1-off, 'y':y1-off}, {'x': x2+off, 'y':y1-off}, {'x': x2+off, 'y':y2+off}, {'x': x_boss, 'y':y2+off}, {'x': x_boss, 'y':boss_y} ], layer='F.SilkS', width=configuration['silk_line_width']) kicad_mod.append(out_silk) kicad_mod.append(Arc(center=[0,boss_y], start=[-x_boss, boss_y], angle=-180, layer="F.SilkS", width=configuration['silk_line_width'])) out_fab = PolygoneLine(polygone=[ {'x': -boss_size_1pin/2, 'y':boss_y}, {'x': -boss_size_1pin/2, 'y':y2}, {'x': x1, 'y':y2}, {'x': x1, 'y':y1}, {'x': x2, 'y':y1}, {'x': x2, 'y':y2}, {'x': boss_size_1pin/2, 'y':y2}, {'x': boss_size_1pin/2, 'y':boss_y} ], layer='F.Fab', width=configuration['fab_line_width']) kicad_mod.append(out_fab) kicad_mod.append(Arc(center=[0,boss_y], start=[-boss_size_1pin/2, boss_y], angle=-180, layer="F.Fab", width=configuration['fab_line_width'])) else: out = RectLine(start=[x1,y1], end=[x2,y2], offset=configuration['silk_fab_offset'], layer='F.SilkS', width=configuration['silk_line_width']) kicad_mod.append(out) body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #draw the courtyard cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if boss and pins == 1: cy2 = roundToBase(boss_y+boss_drill/2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #draw the connector outline if fab_pin1_marker_type == 2: fab_marker_left = -fab_first_marker_w/2.0 fab_marker_bottom = y1 + fab_first_marker_h poly_fab_marker = [ {'x':fab_marker_left, 'y':y1}, {'x':0, 'y':fab_marker_bottom}, {'x':fab_marker_left + fab_first_marker_w, 'y':y1} ] kicad_mod.append(PolygoneLine(polygone=poly_fab_marker, layer='F.Fab', width=configuration['fab_line_width'])) #wall thickness w w = 0.75 #gap size g g = 1.5 off = 0.1 x1 -= off y1 -= off x2 += off y2 += off #draw the center tab kicad_mod.append(RectLine(start=[g/2,y1], end=[A-g/2,y1+w], layer='F.SilkS', width=configuration['silk_line_width'])) #add left tab kicad_mod.append(RectLine(start=[x1,y1], end=[-g/2,y1+w], layer='F.SilkS', width=configuration['silk_line_width'])) #right tab kicad_mod.append(RectLine(start=[A+g/2,y1], end=[x2,y1+w], layer='F.SilkS', width=configuration['silk_line_width'])) #add other line line = [ {'x': x1,'y': y1+w+g}, {'x': x1+w,'y': y1+w+g}, {'x': x1+w,'y': y2-w}, {'x': A/2,'y': y2-w} ] if boss and pins > 1: line2 = line[:2] line2.append({'x': x1+w,'y': boss_y - boss_drill/2 - configuration['silk_line_width']/2 - configuration['silk_pad_clearance']}) kicad_mod.append(PolygoneLine(polygone=line2, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[A/2, y2-w], end=[boss_x+boss_drill/2+ configuration['silk_line_width']/2 + configuration['silk_pad_clearance'], y2-w], layer='F.SilkS', width=configuration['silk_line_width'])) else: kicad_mod.append(PolygoneLine(polygone=line, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=line, x_mirror=A/2, layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 marker y = -2.75 m = 0.3 poly_pin1_marker = [ {'x':x1-pin1_marker_offset+pin1_marker_linelen, 'y':y1-pin1_marker_offset}, {'x':x1-pin1_marker_offset, 'y':y1-pin1_marker_offset}, {'x':x1-pin1_marker_offset, 'y':y1-pin1_marker_offset+pin1_marker_linelen} ] if fab_pin1_marker_type == 2: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 3: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) pin = [ {'x': 0,'y': y}, {'x': -m,'y': y-2*m}, {'x': m,'y': y-2*m}, {'x': 0,'y': y}, ] if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### text_center_y = 'bottom' addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pincount in variant_params[variant]['pin_range']: generate_one_footprint(pincount, variant, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_ze_tht_side.py ================================================ #!/usr/bin/env python3 import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from math import floor,ceil series = "ZE" manufacturer = 'JST' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eZE.pdf' pitch = 1.5 y_spacing = 3.70 drill = 0.75 # 0.7 +0.1/-0.1 -> 0.75 +/-0.05 pad_size = [1.4, 1.75] # Using same pad size as top entry mh_drill = 1.15 def generate_one_footprint(pincount, configuration): mpn = "S{pincount:02}B-ZESK-2D".format(pincount=pincount) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #dimensions A = (pincount - 1) * 1.5 B = A + 4.5 #outline x1 = -1.55 - 0.7 x2 = x1 + B xMid = x1 + B/2 y2 = 3.7 + 3.65 y1 = y2 - 7.8 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #add outline to F.Fab kicad_mod.append(RectLine( start={'x': x1, 'y': y1}, end={'x': x2, 'y': y2}, layer='F.Fab', width=configuration['fab_line_width'] )) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if y1 < -pad_size[1]/2: cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) else: cy1 = roundToBase(-pad_size[1]/2-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) #expand the outline a little bit out = configuration['silk_fab_offset'] x1 -= out x2 += out y1 -= out y2 += out silk_pad_offset = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] if y1 < -(pad_size[1]/2 + silk_pad_offset): kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, width=configuration['silk_line_width'], layer="F.SilkS")) else: num_odd_pins = ceil(pincount/2) pos_last_odd_pad = (num_odd_pins-1) * 2*pitch poly_silk = [ {'x': -(pad_size[0]/2 + silk_pad_offset), 'y': y1}, {'x': x1, 'y': y1}, {'x': x1, 'y': y2}, {'x': x2, 'y': y2}, {'x': x2, 'y': y1}, {'x': pos_last_odd_pad + (pad_size[0]/2 + silk_pad_offset), 'y': y1}, ] kicad_mod.append(PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS")) for i in range(num_odd_pins-1): kicad_mod.append(Line(start=[i * 2*pitch + (pad_size[0]/2 + silk_pad_offset), y1], end=[(i+1) * 2*pitch - (pad_size[0]/2 + silk_pad_offset), y1], width=configuration['silk_line_width'], layer="F.SilkS")) # create odd numbered pads #createNumberedPadsTHT(kicad_mod, ceil(pincount/2), pitch * 2, drill, pad_size, increment=2) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( initial=row_idx+1, start=[row_idx*pitch, row_idx*y_spacing], x_spacing=pitch*2, pincount=ceil(pincount/2) if row_idx == 0 else floor(pincount/2), size=pad_size, drill=drill, increment=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) #create even numbered pads #createNumberedPadsTHT(kicad_mod, floor(pincount/2), pitch * 2, drill, pad_size, starting=2, increment=2, y_off=y_spacing, x_off=pitch) #add mounting holes # kicad_mod.append(MountingHole( # {'x': -1.55, 'y': 1.85}, # 1.1 # )) # # kicad_mod.append(MountingHole( # {'x': A+1.55 , 'y': 1.85}, # 1.1 # ) kicad_mod.append(Pad(at={'x': -1.55, 'y': 1.85}, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH, drill=mh_drill, size=mh_drill)) kicad_mod.append(Pad(at={'x': A+1.55, 'y': 1.85}, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH, drill=mh_drill, size=mh_drill)) #draw the line at the bottom xa = xMid - A/2 + out xb = xMid + A/2 - out y3 = y2 - 1 kicad_mod.append(PolygoneLine(polygone=[ {'x':xa,'y':y2}, {'x':xa,'y':y3}, {'x':xb,'y':y3}, {'x':xb,'y':y2} ], width=configuration['silk_line_width'], layer="F.SilkS")) # add pin-1 marker D = 0.3 L = 1.5 pin_1 = [ {'x': x1-D,'y': y1-D+L}, {'x': x1-D,'y': y1-D}, {'x': x1-D + L,'y': y1-D}, ] kicad_mod.append(PolygoneLine(polygone=pin_1, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine(polygone=pin_1, layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2, 17): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_JST/conn_jst_ze_tht_top.py ================================================ #!/usr/bin/env python3 import sys import os sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) from math import floor,ceil # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "ZE" manufacturer = 'JST' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.jst-mfg.com/product/pdf/eng/eZE.pdf' #ZE connector, top-entry THT, NO BOSS pitch = 1.5 y_spacing = 2.0 drill = 0.75 # 0.7 +0.1/-0.0 -> 0.75 +/-0.05 mh_drill = 0.85 pad_size = [1.4, 1.75] # Measurements from freecad sketch (pad to pad clearance > 0.8 for a 45° trace.) variant_parameters = { '1D': { 'boss':True, 'pin_range':range(2,17), 'descr_str':', with boss' }, 'D': { 'boss':False, 'pin_range':range(3,17), 'descr_str':'' } } def generate_one_footprint(pincount, variant, configuration): mpn = "B{pincount:02}B-ZESK-{suff}".format(pincount=pincount,suff=variant) boss = variant_parameters[variant]['boss'] orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("JST {:s} series connector, {:s}{:s} ({:s}), generated with kicad-footprint-generator"\ .format(series, mpn, variant_parameters[variant]['descr_str'], datasheet)) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) if boss: tags += ' boss' kicad_mod.setTags(tags) #dimensions A = (pincount - 1) * 1.5 B = A + 4.5 #outline x1 = -1.55 - 0.7 x2 = x1 + B xMid = x1 + B/2 y2 = 0.65 y1 = y2 - 5.75 body_edge={'left':x1, 'right':x2, 'top':y1, 'bottom':y2} #add outline to F.Fab kicad_mod.append(RectLine( start={'x': x1, 'y': y1}, end={'x': x2, 'y': y2}, layer='F.Fab', width=configuration['fab_line_width'] )) ########################### CrtYd ################################# cx1 = roundToBase(x1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if y1 < -pad_size[1]/2: cy1 = roundToBase(y1-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) else: cy1 = roundToBase(-pad_size[1]/2-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(x2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(y2+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) # create odd numbered pads # createNumberedPadsTHT(kicad_mod, ceil(pincount/2), pitch * 2, drill, {'x':dia, 'y':dia}, increment=2) #special treatment for pin 1 (rectangular pad alone would reduce the clearance too much) if configuration['kicad4_compatible']: kicad_mod.append(Pad(number=1, at=[0, 0], size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number=1, at=[-pad_size[0]/4, 0], size=[pad_size[0]/2,pad_size[1]], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=['F.Cu', 'F.Mask'])) kicad_mod.append(Pad(number=1, at=[-pad_size[0]/4, 0], size=[pad_size[0]/2,pad_size[1]], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=['B.Cu', 'B.Mask'])) else: kicad_mod.append(ChamferedPad(number=1, at=[0, 0], size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, chamfer_size=0.4, radius_ratio=0.25, maximum_radius=0.25, corner_selection=CornerSelection({CornerSelection.TOP_RIGHT:True}))) if pincount > 2: kicad_mod.append(PadArray(initial=3, start=[2*pitch, 0], x_spacing=pitch*2, pincount=ceil(pincount/2)-1, size=pad_size, drill=drill, increment=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT)) #create even numbered pads # createNumberedPadsTHT(kicad_mod, floor(pincount/2), pitch * 2, drill, {'x':dia, 'y':dia}, starting=2, increment=2, y_off=y_spacing, x_off=pitch) kicad_mod.append(PadArray(initial=2, start=[pitch, -y_spacing], x_spacing=pitch*2, pincount=floor(pincount/2), size=pad_size, drill=drill, increment=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT)) #expand the outline a little bit out = configuration['silk_fab_offset'] x1 -= out x2 += out y1 -= out y2 += out silk_pad_offset = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] if y2 > (pad_size[1]/2 + silk_pad_offset): kicad_mod.append(RectLine(start={'x':x1,'y':y1}, end={'x':x2,'y':y2}, width=configuration['silk_line_width'], layer="F.SilkS")) else: num_odd_pins = ceil(pincount/2) pos_last_odd_pad = (num_odd_pins-1) * 2*pitch poly_silk = [ {'x': -(pad_size[0]/2 + silk_pad_offset), 'y': y2}, {'x': x1, 'y': y2}, {'x': x1, 'y': y1}, {'x': x2, 'y': y1}, {'x': x2, 'y': y2}, {'x': pos_last_odd_pad + (pad_size[0]/2 + silk_pad_offset), 'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS")) for i in range(num_odd_pins-1): kicad_mod.append(Line(start=[i * 2*pitch + (pad_size[0]/2 + silk_pad_offset), y2], end=[(i+1) * 2*pitch - (pad_size[0]/2 + silk_pad_offset), y2], width=configuration['silk_line_width'], layer="F.SilkS")) #add mounting hole (only for the -1D option which has the boss) if boss: # kicad_mod.append(MountingHole( # {'x': -1.65, 'y': -3.8}, # 1.1 # ) kicad_mod.append(Pad(at={'x': -1.65, 'y': -3.8}, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH, drill=mh_drill, size=mh_drill)) #thicknes t of sidewalls t = 0.8 xa = xMid - A/2 - 0.25 + out xb = xMid + A/2 + 0.25 - out y3 = y1 + 1.7 q = 0.4 #inner rect offset #outer rect kicad_mod.append(RectLine( start={'x': xa,'y': y1}, end={'x': xb,'y': y3}, width=configuration['silk_line_width'], layer="F.SilkS" )) #inner rect kicad_mod.append(RectLine( start={'x': xa+q,'y': y1+q}, end={'x': xb-q,'y': y3-q}, width=configuration['silk_line_width'], layer="F.SilkS" )) #left side if not boss: kicad_mod.append(PolygoneLine(polygone=[ {'x': xa,'y': y3}, {'x': x1+t,'y':y3}, {'x': x1+t,'y':y2-t}, {'x': -1,'y':y2-t}, ], width=configuration['silk_line_width'], layer="F.SilkS")) else: #boss were declared kicad_mod.append(Line( start={'x': xa,'y': y3}, end={'x': -0.9,'y': y3}, width=configuration['silk_line_width'], layer="F.SilkS" )) kicad_mod.append(PolygoneLine(polygone=[ {'x': x1+t,'y': -3}, {'x': x1+t,'y': y2-t}, {'x': -1,'y': y2-t}, ], width=configuration['silk_line_width'], layer="F.SilkS")) #right side if pincount %2 == 0: #even number of pins xEnd = (pincount / 2 - 1) * (2 * pitch) + 1 else: xEnd = floor(pincount / 2) * (2 * pitch) + 1 kicad_mod.append(PolygoneLine(polygone=[ {'x': xb,'y': y3}, {'x': x2-t,'y': y3}, {'x': x2-t,'y': y2-t}, {'x': xEnd,'y': y2-t}, ], width=configuration['silk_line_width'], layer="F.SilkS")) #draw lines between pads for i in range(0, ceil(pincount/2) - 1): X1 = i * 2 * pitch + pad_size[1]/2 + silk_pad_offset X2 = (i + 1) * 2 * pitch - (pad_size[1]/2 + silk_pad_offset) kicad_mod.append(Line( start={'x': X1,'y': y2-t}, end={'x': X2,'y': y2-t}, width=configuration['silk_line_width'], layer='F.SilkS')) #draw the 'vertical' lines where the actual pinny bits go #width of each slot w w = 0.15 #clearance distance d d = 0.3 # for i in range(pincount): # # x = i * pitch # # Y1 = y3 + d # Y2 = -pad_size[1]/2 - d # # kicad_mod.append(RectLine(start={'x':x-w, 'y': Y1}, # end={'x':x+w, 'y': Y2}, # width=configuration['fab_line_width'], layer='F.Fab')) # add pin-1 marking above the pin1 d = 0.3 l = 1.5 xp1 = x1 - d xp2 = xp1 + l yp2 = y2 + d yp1 = yp2 - l pin1 = [ {'x': xp1,'y': yp1}, {'x': xp1,'y': yp2}, {'x': xp2,'y': yp2}, ] kicad_mod.append(PolygoneLine(polygone=pin1,width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=pin1,layer='F.Fab', width=configuration['fab_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_parameters: for pincount in variant_parameters[variant]['pin_range']: generate_one_footprint(pincount, variant, configuration) ================================================ FILE: scripts/Connector/Connector_JST/helpers.py ================================================ def roundToBase(value, base): return round(value/base) * base ================================================ FILE: scripts/Connector/Connector_Molex/00-SMD footprint generators can be found in Connector_SMD_single_row_plus_mounting_pad.md ================================================ The following connector footprints are generated in the generic scirpt located in ../Connector_SMD_single_row_plus_mounting_pad/ - 'Panelmate' - '53780-{pincount:02d}70' - 'Pico-EZmate' - '78171-00{pincount:02d}' - 'Pico-EZmate_Slim' - '202656-0{pincount:02d}1' - 'PicoBlade' - '53398-{pincount:02d}71' - 'PicoBlade' - '53261-{pincount:02d}71' - 'Pico-Clasp' - '501331-{pincount:02d}07' - 'Pico-Clasp' - '501331-{pincount:02d}07' - 'Pico-Clasp' - '202396-{pincount:02d}07' - 'Pico-Lock' - '504050-{pincount:02d}91' ================================================ FILE: scripts/Connector/Connector_Molex/conn_ffc_molex_200528.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from footprint_keepout_area import addRectangularKeepout pinrange = range(4, 31) # 4-30 circuits series = "" series_long = ('Molex 1.00mm Pitch Easy-On BackFlip, ' + 'Right-Angle, Bottom Contact FFC/FPC') manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 conn_category = "FFC-FPC" lib_by_conn_category = True part_code = "200528-0{:02d}0" pitch = 1.0 pad_size = (0.4, 1.0) mp_size = (2.0, 1.3) foot_y = 3.95 toe_size = (0.55, 0.35) lead_size = (0.15, pad_size[1] - 0.6) def make_module(pin_count, configuration): mpn = part_code.format(pin_count) datasheet='https://www.molex.com/pdm_docs/sd/2005280{:02d}0_sd.pdf'.format(pin_count) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man = manufacturer, series = series, mpn = mpn, num_rows = number_of_rows, pins = pin_count, pins_per_row = pin_count, mounting_pad = "-1MP", pitch = pitch, orientation = orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription( ("Molex {:s}, {:s}, {:d} Circuits ({:s}), " + "generated with kicad-footprint-generator").format( series_long, mpn, pin_count, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format( man=manufacturer, series=series, orientation=orientation_str, entry=configuration['entry_direction'][orientation])) A = pin_count + 5.2 B = pin_span = pin_count - 1 C = pin_count + 3.6 pin_y = -(0.4 - (lead_size[1] / 2)) - 0.71 lever_size = (C, 4) toe_ins_corner = ((A / 2) - toe_size[0], pin_y + (0.4 - (lead_size[1] / 2))) lever_out_corner = (C / 2, (toe_ins_corner[1] - toe_size[1]) + 5.25) pad_silk_off = (configuration['silk_pad_clearance'] + (configuration['silk_line_width'] / 2)) fab_silk_off = configuration['silk_fab_offset'] ## Mounting Pads ## mp_pos = ((pin_span / 2) + 1.8 + (mp_size[0] / 2), pin_y + (pad_size[1] / 2) + 1.55 + (mp_size[1] / 2)) def make_anchor_pad(x_direction): kicad_mod.append( Pad(number = configuration['mounting_pad_number'], type = Pad.TYPE_SMT, shape = Pad.SHAPE_RECT, at = [x_direction * mp_pos[0], mp_pos[1]], size = mp_size, layers = Pad.LAYERS_SMT)) make_anchor_pad(-1) make_anchor_pad(1) ## Pads ## kicad_mod.append( PadArray(center = [0, pin_y], pincount = pin_count, x_spacing = pitch, type = Pad.TYPE_SMT, shape = Pad.SHAPE_RECT, size = pad_size, layers = Pad.LAYERS_SMT)) ## Fab ## fab_body_outline = [ {'x': toe_ins_corner[0], 'y': toe_ins_corner[1] - toe_size[1]}, {'x': toe_ins_corner[0], 'y': toe_ins_corner[1]}, {'x': -toe_ins_corner[0], 'y': toe_ins_corner[1]}, {'x': -toe_ins_corner[0], 'y': toe_ins_corner[1] - toe_size[1]}, {'x': -(A / 2), 'y': toe_ins_corner[1] - toe_size[1]}, {'x': -(A / 2), 'y': (toe_ins_corner[1] - toe_size[1]) + foot_y}, {'x': (A / 2), 'y': (toe_ins_corner[1] - toe_size[1]) + foot_y}, {'x': (A / 2), 'y': toe_ins_corner[1] - toe_size[1]}, {'x': toe_ins_corner[0], 'y': toe_ins_corner[1] - toe_size[1]} ] kicad_mod.append(PolygoneLine( polygone = fab_body_outline, layer = 'F.Fab', width = configuration['fab_line_width'])) fab_pin1_mark = [ {'x': -(pin_span / 2) - 0.5, 'y': toe_ins_corner[1]}, {'x': -(pin_span / 2), 'y': toe_ins_corner[1] + 0.75}, {'x': -(pin_span / 2) + 0.5, 'y': toe_ins_corner[1]} ] kicad_mod.append(PolygoneLine( polygone = fab_pin1_mark, layer = 'F.Fab', width = configuration['fab_line_width'])) fab_lever_outline = [ {'x': lever_out_corner[0], 'y': lever_out_corner[1] - lever_size[1]}, {'x': -lever_out_corner[0], 'y': lever_out_corner[1] - lever_size[1]}, {'x': -lever_out_corner[0], 'y': lever_out_corner[1]}, {'x': lever_out_corner[0], 'y': lever_out_corner[1]}, {'x': lever_out_corner[0], 'y': lever_out_corner[1] - lever_size[1]} ] kicad_mod.append(PolygoneLine( polygone = fab_lever_outline, layer = 'F.Fab', width = configuration['fab_line_width'])) ## SilkS ## silk_outline1 = [ {'x': (-(pin_span / 2) - (pad_size[0] / 2)) - pad_silk_off, 'y': pin_y - (pad_size[1] / 2)}, {'x': (-(pin_span / 2) - (pad_size[0] / 2)) - pad_silk_off, 'y': toe_ins_corner[1] - fab_silk_off}, {'x': -toe_ins_corner[0] + fab_silk_off, 'y': toe_ins_corner[1] - fab_silk_off}, {'x': -toe_ins_corner[0] + fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': -(A / 2) - fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': -(A / 2) - fab_silk_off, 'y': (mp_pos[1] - (mp_size[1] / 2)) - pad_silk_off}, ] silk_outline2 = [ {'x': -(A / 2) - fab_silk_off, 'y': (mp_pos[1] + (mp_size[1] / 2)) + pad_silk_off}, {'x': -(A / 2) - fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': -lever_out_corner[0] - fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': -lever_out_corner[0] - fab_silk_off, 'y': lever_out_corner[1] + fab_silk_off}, {'x': lever_out_corner[0] + fab_silk_off, 'y': lever_out_corner[1] + fab_silk_off}, {'x': lever_out_corner[0] + fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': (A / 2) + fab_silk_off, 'y': ((toe_ins_corner[1] - toe_size[1]) + foot_y) + fab_silk_off}, {'x': (A / 2) + fab_silk_off, 'y': (mp_pos[1] + (mp_size[1] / 2)) + pad_silk_off}, ] silk_outline3 = [ {'x': (A / 2) + fab_silk_off, 'y': (mp_pos[1] - (mp_size[1] / 2)) - pad_silk_off}, {'x': (A / 2) + fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': toe_ins_corner[0] - fab_silk_off, 'y': (toe_ins_corner[1] - toe_size[1]) - fab_silk_off}, {'x': toe_ins_corner[0] - fab_silk_off, 'y': toe_ins_corner[1] - fab_silk_off}, {'x': ((pin_span / 2) + (pad_size[0] / 2)) + pad_silk_off, 'y': toe_ins_corner[1] - fab_silk_off} ] kicad_mod.append(PolygoneLine( polygone = silk_outline1, layer = 'F.SilkS', width = configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone = silk_outline2, layer = 'F.SilkS', width = configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone = silk_outline3, layer = 'F.SilkS', width = configuration['silk_line_width'])) ## CrtYd ## bounding_box = { 'top': pin_y - (pad_size[1] / 2), 'left': (-mp_pos[0] - (mp_size[0] / 2)), 'bottom': lever_out_corner[1], 'right': (mp_pos[0] + (mp_size[0] / 2))} cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ## Text ## addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=bounding_box, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pincount in pinrange: make_module(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_ffc_molex_502250.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from footprint_keepout_area import addRectangularKeepout pinrange = [17, 21, 23, 27, 33, 35, 39, 41, 51] series = "" series_long = 'Molex 0.30mm Pitch Easy-On BackFlip Type FFC/FPC' manufacturer = 'Molex' orientation = 'H' number_of_rows = 2 conn_category = "FFC-FPC" lib_by_conn_category = True part_code = "502250-{0}91" # def get_name(pin_count): # return 'Molex-502250-{0}91_2Rows-{0}Pins_P0.3mm_Horizontal'.format(pin_count) cable_pitch = 0.3 odd_pad_size = (0.80, 0.26) # bottom even_pad_size = (0.65, 0.3) # top anchor_pad_size = (0.85, 0.4) def make_module(pin_count, configuration): pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] off = configuration['silk_fab_offset'] datasheet='http://www.molex.com/pdm_docs/sd/502250{0}91_sd.pdf'.format(pin_count) mpn = part_code.format(pin_count) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_unequal_row_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins=pin_count, mounting_pad = "-1MP", pitch=cable_pitch*2, orientation=orientation_str) footprint_name = footprint_name.replace("__",'_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Circuits ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pin_count, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) TL = 0.25 TW = 0.3 gab_anchor_L = 0.4 gab_anchor_W = 0.3 pad_to_pad_outside = 3.6 row_spacing = pad_to_pad_outside - odd_pad_size[0]/2 - even_pad_size[0]/2 odd_pad_x = -pad_to_pad_outside/2 + odd_pad_size[0]/2 even_pad_x = odd_pad_x + row_spacing pins_width = cable_pitch * (pin_count - 1) anchor_pad_spacing = pins_width + 1.4 anchor_pad_x = odd_pad_x - odd_pad_size[0]/2 + (0.3 + anchor_pad_size[0]/2) width = pins_width + 2.1 bar_width = pins_width + 0.48 body_edge = { 'top': -width/2, 'bottom': width/2, 'left': anchor_pad_x -0.55/2 - 0.36 } body_edge['right'] = body_edge['left'] + 3.53 - TL bar_down_edge = body_edge['left'] + 4.19 ctyd_width = anchor_pad_spacing + anchor_pad_size[0]# + 1.0 bounding_box = { 'top': -ctyd_width/2, 'bottom': ctyd_width/2, 'left': odd_pad_x - odd_pad_size[0]/2, 'right': bar_down_edge } fab_outline = [ {'x': body_edge['left'], 'y':0}, {'x': body_edge['left'], 'y':body_edge['bottom']}, {'x': anchor_pad_x - gab_anchor_L/2, 'y':body_edge['bottom']}, {'x': anchor_pad_x - gab_anchor_L/2, 'y':body_edge['bottom'] - gab_anchor_W}, {'x': anchor_pad_x + gab_anchor_L/2, 'y':body_edge['bottom'] - gab_anchor_W}, {'x': anchor_pad_x + gab_anchor_L/2, 'y':body_edge['bottom']}, {'x': body_edge['right'] + TL, 'y':body_edge['bottom']}, {'x': body_edge['right'] + TL, 'y':body_edge['bottom']-TW}, {'x': body_edge['right'], 'y':body_edge['bottom']-TW}, {'x': body_edge['right'], 'y':0} ] kicad_mod.append(PolygoneLine( polygone=fab_outline, layer="F.Fab", width=configuration['fab_line_width'] )) kicad_mod.append(PolygoneLine( polygone=fab_outline, y_mirror=0, layer="F.Fab", width=configuration['fab_line_width'] )) kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['right'], 'y': -bar_width/2}, {'x': bar_down_edge, 'y': -bar_width/2}, {'x': bar_down_edge, 'y': bar_width/2}, {'x': body_edge['right'], 'y': bar_width/2} ], layer="F.Fab", width=configuration['fab_line_width'] )) odd_pins_outside = pins_width/2 + odd_pad_size[0]/2 + pad_silk_off silk_outline = [ {'x': body_edge['left']-off, 'y':odd_pins_outside}, {'x': body_edge['left']-off, 'y':body_edge['bottom']+off}, {'x': body_edge['right'] + TL + off, 'y':body_edge['bottom']+off}, {'x': body_edge['right'] + TL + off, 'y':body_edge['bottom']-TW - off}, {'x': body_edge['right'] + off, 'y':body_edge['bottom']-TW - off}, {'x': body_edge['right'] + off, 'y': bar_width/2 + off}, {'x': bar_down_edge + off, 'y': bar_width/2 + off}, {'x': bar_down_edge + off, 'y': 0} ] kicad_mod.append(PolygoneLine( polygone=silk_outline, layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(PolygoneLine( polygone=silk_outline, y_mirror=0, layer="F.SilkS", width=configuration['silk_line_width'] )) even_pins = pin_count//2 odd_pins = pin_count - even_pins kicad_mod.append(PadArray( center=[odd_pad_x,0], pincount=odd_pins, initial=1, increment=2, y_spacing=2*cable_pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=odd_pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray( center=[even_pad_x, 0], pincount=even_pins, initial=2, increment=2, y_spacing=2*cable_pitch, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=even_pad_size, layers=Pad.LAYERS_SMT)) def anchor_pad(direction): # f.write(" (pad \"\" smd rect (at {x:1.5g} {y:1.5g}) " # "(size {pad_size[0]} {pad_size[1]}) " # "(layers F.Cu F.Paste F.Mask))\n".format( # x=anchor_pad_spacing / 2 * direction, # y=0.325 - row_spacing/2 + y_offset, # pad_size=anchor_pad_size)) kicad_mod.append(Pad(number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[anchor_pad_x, anchor_pad_spacing / 2 * direction], size=anchor_pad_size, layers=Pad.LAYERS_SMT)) anchor_pad(-1) anchor_pad(1) pin1_y = -pins_width/2 ps1_m = 0.3 p1s_x = bounding_box['left'] - pad_silk_off pin = [ {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y-ps1_m/2}, {'x': p1s_x, 'y': pin1_y}, {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y+ps1_m/2}, {'x': p1s_x - ps1_m/sqrt(2), 'y': pin1_y-ps1_m/2} ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) sl=0.6 pin = [ {'x': body_edge['left'], 'y': pin1_y-sl/2}, {'x': body_edge['left'] + sl/sqrt(2), 'y': pin1_y}, {'x': body_edge['left'], 'y': pin1_y+sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pincount in pinrange: make_module(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_SPOX_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SPOX" series_long = 'SPOX Connector System' manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 datasheet = 'https://www.molex.com/pdm_docs/sd/022057045_sd.pdf' #pins_per_row per row pins_per_row_range = range(2, 16) #Molex part number #n = number of circuits per row part_code = "5268-{n:02}A" pitch = 2.5 drill = 0.85 pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2 * max_annular_ring] if pad_size[0] - drill < 2 * min_annular_ring: pad_size[0] = drill + 2 * min_annular_ring if pad_size[0] - drill > 2 * max_annular_ring: pad_size[0] = drill + 2 * max_annular_ring pad_shape = Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n = pins_per_row * number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man = manufacturer, series = series, mpn = mpn, num_rows = number_of_rows, pins_per_row = pins_per_row, mounting_pad = "", pitch = pitch, orientation = orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series = series, orientation = orientation_str, man = manufacturer, entry = configuration['entry_direction'][orientation])) A = (pins_per_row - 1) * pitch C = A + 2 * 2.45 #connector width W = 7.9 chamfer_pin_n = {'x': 1, 'y': 1} off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width'] / 2 body_edge = {} body_edge['left'] = (A - C) / 2 body_edge['right'] = body_edge['left'] + C body_edge['top'] = -(7.9 - 6.6) body_edge['bottom'] = body_edge['top'] + W bounding_box = body_edge.copy() # generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start = [0, 0], pincount = pins_per_row, x_spacing = pitch, type = Pad.TYPE_THT, shape = pad_shape, size = pad_size, drill = drill, layers = Pad.LAYERS_THT, **optional_pad_params)) def generateOutline(off = 0, grid = 0): poly = [ {'x': body_edge['left'] - off, 'y': body_edge['top'] - off}, {'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off}, {'x': body_edge['right']+off, 'y':body_edge['bottom'] +off}, {'x': body_edge['right'] + off, 'y': body_edge['top'] - off}, {'x': body_edge['left'] - off, 'y': body_edge['top'] - off}, ] if grid == 0: return poly else: return [{'x': roundToBase(p['x'], grid), 'y': roundToBase(p['y'], grid)} for p in poly] # outline on Fab kicad_mod.append(PolygoneLine(polygone = generateOutline(), layer = 'F.Fab', width = configuration['fab_line_width'])) # outline on SilkScreen kicad_mod.append(PolygoneLine(polygone = generateOutline(off = off), layer = 'F.SilkS', width = configuration['silk_line_width'])) #pin-1 mark sl = 2 o = off + 0.3 pin = [ {'y': body_edge['top'] + sl, 'x': body_edge['left'] - o}, {'y': body_edge['top'] - o, 'x': body_edge['left'] - o}, {'y': body_edge['top'] - o, 'x': body_edge['left'] + sl} ] kicad_mod.append(PolygoneLine(polygone = pin, layer = 'F.SilkS', width = configuration['silk_line_width'])) sl = 1 pin = [ {'y': sl / 2, 'x': body_edge['left']}, {'y': 0, 'x': body_edge['left'] + sl / sqrt(2)}, {'y': -sl / 2, 'x': body_edge['left']} ] kicad_mod.append(PolygoneLine(polygone = pin, width = configuration['fab_line_width'], layer = 'F.Fab')) ########################### CrtYd ################################# poly_crtyd = generateOutline(configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = poly_crtyd[0]['y'] cy2 = poly_crtyd[1]['y'] kicad_mod.append(PolygoneLine( polygone = poly_crtyd, layer = 'F.CrtYd', width = configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod = kicad_mod, configuration = configuration, body_edges = body_edge, courtyard = {'top': cy1, 'bottom': cy2}, fp_name = footprint_name, text_y_inside_position = 'bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series = series, man = manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix = model3d_path_prefix, lib_name = lib_name, fp_name = footprint_name) kicad_mod.append(Model(filename = model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name = lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir = output_dir, fp_name = footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_SPOX_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SPOX" series_long = 'SPOX Connector System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/022035035_sd.pdf' #pins_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row part_code = "5267-{n:02}A" pitch = 2.5 drill = 0.85 pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n=pins_per_row*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins_per_row - 1) * pitch B = A + 2*1.75 C = A + 2*2.45 #connector width W = 4.9 chamfer_pin_n = {'x': 1, 'y': 1} off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge={} body_edge['left'] = (A - C) / 2 body_edge['right'] = body_edge['left'] + C body_edge['top'] = -3.1 body_edge['bottom'] = body_edge['top'] + W bounding_box = body_edge.copy() # generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[0,0], pincount=pins_per_row, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) def generateOutline(off = 0, grid = 0): poly = [ {'x': body_edge['left']-off, 'y':body_edge['top']-off}, {'x': body_edge['left']-off, 'y':body_edge['bottom']+off}, {'x': body_edge['right']-chamfer_pin_n['x']+off, 'y':body_edge['bottom']+off}, {'x': body_edge['right']+off, 'y':body_edge['bottom']-chamfer_pin_n['y']+off}, {'x': body_edge['right']+off, 'y':body_edge['top']-off}, {'x': body_edge['left']-off, 'y':body_edge['top']-off}, ] if grid == 0: return poly else: return [{'x':roundToBase(p['x'], grid), 'y':roundToBase(p['y'], grid)} for p in poly] # outline on Fab kicad_mod.append(PolygoneLine(polygone=generateOutline(), layer='F.Fab', width=configuration['fab_line_width'])) # outline on SilkScreen kicad_mod.append(PolygoneLine(polygone=generateOutline(off=off), layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 mark sl=2 o = off + 0.3 pin = [ {'y': body_edge['bottom'] - sl, 'x': body_edge['left'] - o}, {'y': body_edge['bottom'] + o, 'x': body_edge['left'] - o}, {'y': body_edge['bottom'] + o, 'x': body_edge['left'] + sl} ] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['bottom'], 'x': -sl/2}, {'y': body_edge['bottom'] - sl/sqrt(2), 'x': 0}, {'y': body_edge['bottom'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# poly_crtyd = generateOutline(configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = poly_crtyd[0]['y'] cy2 = poly_crtyd[1]['y'] kicad_mod.append(PolygoneLine( polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_kk_254_tht_top.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "KK-254" series_long = 'KK-254 Interconnect System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/022272021_sd.pdf' pitch = 2.54 drill = 1.19 # from datasheet start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE eng_mpn = 'AE-6410-{n:02d}A' new_mpn_example = '22-27-2{n:02d}1' def generate_one_footprint(pincount, configuration): mpn = eng_mpn.format(n=pincount) new_mpn = new_mpn_example.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old/engineering part number: {:s} example for new part number: {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format(series_long, mpn, new_mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # calculate working values end_pos_x = (pincount-1) * pitch centre_x = (end_pos_x - start_pos_x) / 2.0 nudge = configuration['silk_fab_offset'] silk_w = configuration['silk_line_width'] fab_w = configuration['fab_line_width'] body_edge={ 'left':start_pos_x - pitch/2, 'right':end_pos_x + pitch/2, 'bottom':1.88+1 } body_edge['top'] = body_edge['bottom']-5.8 # create pads # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[start_pos_x, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) # create fab outline kicad_mod.append(RectLine(start=[body_edge['left'], body_edge['top']],\ end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=fab_w)) # create silkscreen kicad_mod.append(RectLine(start=[body_edge['left']-nudge, body_edge['top']-nudge],\ end=[body_edge['right']+nudge, body_edge['bottom']+nudge], layer='F.SilkS', width=silk_w)) # pin 1 markers kicad_mod.append(Line(start=[body_edge['left']-0.4, -2.0],\ end=[body_edge['left']-0.4, 2.0], layer='F.SilkS', width=silk_w)) sl=1 poly_pin1_marker = [ {'x': body_edge['left'], 'y': -sl/2}, {'x': body_edge['left'] + sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': sl/2} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=fab_w)) yr1=body_edge['bottom']+nudge yr2 = yr1 - 1 yr3 = yr2 - 0.53 if pincount <= 6: # one ramp kicad_mod.append(PolygoneLine(polygone=[[start_pos_x, yr1], [start_pos_x, yr2],\ [end_pos_x, yr2], [end_pos_x, yr1]], layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=[[start_pos_x, yr2], [start_pos_x+0.25, yr3],\ [end_pos_x-0.25, yr3], [end_pos_x, yr2] ],layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=[[start_pos_x+0.25, yr1],\ [start_pos_x+0.25, yr2]], layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=[[end_pos_x-0.25, yr1],\ [end_pos_x-0.25, yr2]], layer='F.SilkS', width=silk_w)) else: # two ramps poly1=[ {'x': start_pos_x, 'y': yr1}, {'x': start_pos_x, 'y': yr2}, {'x': start_pos_x+2*pitch, 'y': yr2}, {'x': start_pos_x+2*pitch, 'y': yr1} ] poly2=[ {'x': start_pos_x, 'y': yr2}, {'x': start_pos_x+0.25, 'y': yr3}, {'x': start_pos_x+2*pitch, 'y': yr3}, {'x': start_pos_x+2*pitch, 'y': yr2} ] poly3=[ {'x': start_pos_x+0.25, 'y': yr1}, {'x': start_pos_x+0.25, 'y': yr2} ] kicad_mod.append(PolygoneLine(polygone=poly1, layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=poly2, layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=poly3, layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=poly1, x_mirror=centre_x, layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=poly2, x_mirror=centre_x, layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=poly3, x_mirror=centre_x, layer='F.SilkS', width=silk_w)) for i in range(0, pincount): middle_x = start_pos_x + i * pitch start_x = middle_x - 1.6/2 end_x = middle_x + 1.6/2 y1 = body_edge['top'] - nudge y2 = y1 + 0.6 kicad_mod.append(PolygoneLine(polygone=[[start_x, y1], [start_x, y2],\ [end_x, y2], [end_x, y1]], layer='F.SilkS', width=silk_w)) ########################### CrtYd ################################# cx1 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(body_edge['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(body_edge['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2, 17): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_kk_396_tht_top.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "KK-396" series_long = 'KK 396 Interconnect System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 datasheet = 'https://www.molex.com/pdm_docs/sd/026604020_sd.pdf' pitch = 3.96 drill = 1.7 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 1.2 # How much copper should be in y direction? min_annular_ring = 0.3 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE eng_mpn = 'A-41791-00{n:02d}' new_mpn_example = '26-60-4{n:02d}0' def generate_one_footprint(pincount, configuration): mpn = eng_mpn.format(n=pincount) new_mpn = new_mpn_example.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old/engineering part number: {:s} example for new part number: {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format(series_long, mpn, new_mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # calculate working values end_pos_x = (pincount-1) * pitch centre_x = (end_pos_x - start_pos_x) / 2.0 nudge = configuration['silk_fab_offset'] silk_w = configuration['silk_line_width'] fab_w = configuration['fab_line_width'] body_edge={ 'left':start_pos_x - 1.91, 'right':end_pos_x + 1.91, 'top':-5.11 } body_edge['bottom'] = body_edge['top']+10.01 # create pads # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[start_pos_x, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) offset_ramp_x = 1.905 offset_ramp_y = 1.005 # create fab outline kicad_mod.append(PolygoneLine(polygone=[ [body_edge['left'], body_edge['top']],\ [body_edge['right'], body_edge['top']],\ [body_edge['right'], body_edge['bottom'] - offset_ramp_y],\ [body_edge['right'] - offset_ramp_x, body_edge['bottom'] - offset_ramp_y],\ [body_edge['right'] - offset_ramp_x, body_edge['bottom']],\ [body_edge['left'] + offset_ramp_x, body_edge['bottom']],\ [body_edge['left'] + offset_ramp_x, body_edge['bottom'] - offset_ramp_y],\ [body_edge['left'], body_edge['bottom'] - offset_ramp_y],\ [body_edge['left'], body_edge['top']]], layer='F.Fab', width=fab_w)) # create silkscreen kicad_mod.append(PolygoneLine(polygone=[ [body_edge['left'] - nudge, body_edge['top'] - nudge],\ [body_edge['right'] + nudge, body_edge['top'] - nudge],\ [body_edge['right'] + nudge, body_edge['bottom'] + nudge - offset_ramp_y],\ [body_edge['right'] + nudge - offset_ramp_x, body_edge['bottom'] + nudge - offset_ramp_y],\ [body_edge['right'] + nudge - offset_ramp_x, body_edge['bottom'] + nudge],\ [body_edge['left'] - nudge + offset_ramp_x, body_edge['bottom'] + nudge],\ [body_edge['left'] - nudge + offset_ramp_x, body_edge['bottom'] + nudge - offset_ramp_y],\ [body_edge['left'] - nudge, body_edge['bottom'] + nudge - offset_ramp_y],\ [body_edge['left'] - nudge, body_edge['top'] - nudge]], layer='F.SilkS', width=silk_w)) # pin 1 markers kicad_mod.append(Line(start=[body_edge['left']-0.4, -2.0],\ end=[body_edge['left']-0.4, 2.0], layer='F.SilkS', width=silk_w)) sl=1 poly_pin1_marker = [ {'x': body_edge['left'], 'y': -sl/2}, {'x': body_edge['left'] + sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': sl/2} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=fab_w)) yr1=body_edge['bottom']+nudge yr2 = yr1 - 1.0 yr3 = yr2 - 1.67 ramps_pin_map = { 2: [[1, 2]], 3: [[1, 3]], 4: [[1, 4]], 5: [[1, 5]], 6: [[1, 3], [4, 6]], 7: [[1, 4], [5, 7]], 8: [[1, 4], [5, 8]], 9: [[1, 5], [6, 9]], 10: [[1, 5], [6, 10]], 11: [[1, 6], [7, 11]], 12: [[1, 4], [5, 8], [9, 12]], 13: [[1, 4], [5, 9], [10, 13]], 14: [[1, 5], [6, 9], [10, 14]], 15: [[1, 5], [6, 10], [11, 15]], 16: [[1, 5], [6, 11], [12, 16]], 17: [[1, 6], [7, 11], [12, 17]], 18: [[1, 6], [7, 12], [13, 18]], } for ramp in ramps_pin_map[pincount]: ramp_start_x = start_pos_x + (ramp[0] - 1) * pitch if ramp[0] != 1: ramp_start_x -= 1.5 ramp_end_x = start_pos_x + (ramp[1] - 1) * pitch if ramp[1] != pincount: ramp_end_x += 1.5 kicad_mod.append(PolygoneLine(polygone=[ [ramp_start_x, yr1], [ramp_start_x, yr2],\ [ramp_end_x, yr2], [ramp_end_x, yr1]],\ layer='F.SilkS', width=silk_w)) kicad_mod.append(PolygoneLine(polygone=[ [ramp_start_x, yr2], [ramp_start_x, yr3],\ [ramp_end_x, yr3], [ramp_end_x, yr2]],\ layer='F.SilkS', width=silk_w)) for i in range(0, pincount): middle_x = start_pos_x + i * pitch start_x = middle_x - 1.6/2 end_x = middle_x + 1.6/2 y1 = body_edge['top'] - nudge y2 = y1 + 0.6 kicad_mod.append(PolygoneLine(polygone=[[start_x, y1], [start_x, y2],\ [end_x, y2], [end_x, y1]], layer='F.SilkS', width=silk_w)) ########################### CrtYd ################################# cx1 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(body_edge['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(body_edge['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2, 19): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_mega-fit_tht_side_dual-row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Mega-Fit" series_long = 'Mega-Fit Power Connectors' manufacturer = 'Molex' orientation = 'H' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/1720640002_sd.pdf' #pins_per_row per row pins_per_row_range = [1, 2, 3, 4, 5, 6] #Molex part number #n = number of circuits per row part_code = "76825-00{n:02d}" alternative_codes = [ "172064-00{n:02d}", "172064-10{n:02d}" ] pitch = 5.7 drill = 1.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 1.75 max_annular_ring = 0.95 #How much copper should be in y direction? min_annular_ring = 0.15 row = 5.5 size = row - pad_to_pad_clearance if size - drill < 2*min_annular_ring: size = drill + 2*min_annular_ring if size - drill > max_annular_ring: size = drill + 2*max_annular_ring def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n=pins_per_row*2) alt_mpn = [code.format(n=pins_per_row*2) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions #http://www.molex.com/pdm_docs/sd/768250010_sd.pdf #connector length if pins_per_row == 1: A = 8.35 else: A = pins_per_row * pitch + 0.65 if pins_per_row == 1 or pins_per_row == 2: B = 0 else: B = A - 6.35 #pin centers P = (pins_per_row - 1) * pitch #corner positions for plastic housing outline x1 = -(A-P)/2 x2 = x1 + A y2 = -1.1 y1 = y2 - 14.8 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins_per_row, initial=row_idx*pins_per_row+1, start=[0, row_idx*row], x_spacing=pitch, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) off = configuration['silk_fab_offset'] silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 #add PCB locators r_loc = 3.00 y_loc = -7.3 #two locators if pins_per_row > 2: lx1 = P/2 - B/2 lx2 = P/2 + B/2 kicad_mod.append(Pad(at=[lx1, y_loc],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=r_loc,drill=r_loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[lx2, y_loc],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=r_loc,drill=r_loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Circle(center=[lx1, y_loc],radius=r_loc/2+silk_pad_off, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=[lx2, y_loc],radius=r_loc/2+silk_pad_off, layer='F.SilkS', width=configuration['silk_line_width'])) else: #one locator kicad_mod.append(Pad(at=[P/2,y_loc],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=r_loc, drill=r_loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Circle(center=[P/2,y_loc], radius=r_loc/2+silk_pad_off, layer='F.SilkS', width=configuration['silk_line_width'])) #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) outline = [ {'x': P/2,'y': y1-off}, {'x': x1-off,'y': y1-off}, {'x': x1-off,'y': y2+off}, {'x': -size/2 - silk_pad_off,'y': y2+off}, ] kicad_mod.append(PolygoneLine(polygone=outline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline,x_mirror=P/2 if P != 0 else 0.00000001, layer='F.SilkS', width=configuration['silk_line_width'])) #draw lines between each pin for i in range(pins_per_row-1): xa = i * pitch + size / 2 + silk_pad_off xb = (i+1) * pitch - size / 2 - silk_pad_off kicad_mod.append(Line(start=[xa,y2+off],end=[xb,y2+off], layer='F.SilkS', width=configuration['silk_line_width'])) #draw the pins! o = size/2 + silk_pad_off w = 0.3 for i in range(pins_per_row): x = i * pitch ya = o yb = row - o kicad_mod.append(Line(start=[x-w,ya],end=[x-w,yb], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x+w,ya],end=[x+w,yb], layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 marker x = -2.5 m = 0.3 pin = [ {'x': x,'y': 0}, {'x': x-2*m,'y': +m}, {'x': x-2*m,'y': -m}, {'x': x,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 2 pin = [ {'x': -sl/2, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom']-sl/sqrt(2)}, {'x': sl/2, 'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(body_edge['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(row + size/2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_mega-fit_tht_top_dual_row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "Mega-Fit" series_long = 'Mega-Fit Power Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 #pins_per_row_per_row per row pins_per_row_range = [1, 2, 3, 4, 5, 6] #Molex part number #n = number of circuits per row variant_params = { 'boss':{ 'mount_pins': False, 'datasheet': 'http://www.molex.com/pdm_docs/sd/768290102_sd.pdf', 'part_code': "76829-01{n:02d}", 'alternative_codes': [ "172065-02{n:02d}", "172065-03{n:02d}" ] }, 'mount_pins':{ 'mount_pins': True, 'datasheet': 'http://www.molex.com/pdm_docs/sd/768290004_sd.pdf', 'part_code': "76829-00{n:02d}", 'alternative_codes': [ "172065-00{n:02d}", "172065-10{n:02d}" ] } } pitch = 5.7 drill = 1.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 1.75 max_annular_ring = 0.95 #How much copper should be in y direction? min_annular_ring = 0.15 row = 5.7 size = row - pad_to_pad_clearance if size - drill < 2*min_annular_ring: size = drill + 2*min_annular_ring if size - drill > 2*max_annular_ring: size = drill + 2*max_annular_ring def generate_one_footprint(pins_per_row, variant, configuration): mpn = variant_params[variant]['part_code'].format(n=pins_per_row*2) alt_mpn = [code.format(n=pins_per_row*2) for code in variant_params[variant]['alternative_codes']] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions #connector length if pins_per_row == 1: A = 8.35 else: A = pins_per_row * pitch + 0.65 B = A + 7.04 #pin centers P = (pins_per_row - 1) * pitch #plasic pin-lock centre-distance C = A + 3.99 #print('A: {}, B: {}, C: {}'.format(A,B,C)) #connector width W = 12.48 #corner positions x1 = -(A-P)/2 x2 = x1 + A y2 = 3.47 + row y1 = y2 -W #tab length tab_l = 3.4 #tab width tab_w = 1.55 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['bottom'] = y2 + tab_w optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT #generate the pads for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins_per_row, initial=row_idx*pins_per_row+1, start=[0, row_idx*row], x_spacing=pitch, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) off = configuration['silk_fab_offset'] silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 if variant_params[variant]['mount_pins']: #add PCB locators loc = 3.00 offset = -0.325 lx1 = P/2 - C/2 lx2 = P/2 + C/2 mounting_pin_y = row - offset kicad_mod.append(Pad(at=[lx1, mounting_pin_y],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[lx2, mounting_pin_y],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) #draw outline around the PCB locators #arc distance from pin mount_pin_radius = (B/2 - C/2) bounding_box['left'] = P/2 - B/2 bounding_box['right'] = P/2 + B/2 ######################## Fab ############################ kicad_mod.append(Arc(center=[lx1,mounting_pin_y], start=[lx1,mounting_pin_y+mount_pin_radius], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y-mount_pin_radius], end=[x1,mounting_pin_y-mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y+mount_pin_radius], end=[x1,mounting_pin_y+mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Arc(center=[lx2,mounting_pin_y], start=[lx2,mounting_pin_y-mount_pin_radius], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y-mount_pin_radius], end=[x2,mounting_pin_y-mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y+mount_pin_radius], end=[x2,mounting_pin_y+mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) ######################## Silk ############################ mount_pin_radius = loc/2 + silk_pad_off kicad_mod.append(Arc(center=[lx1,mounting_pin_y], start=[lx1,mounting_pin_y+mount_pin_radius], angle=180, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y-mount_pin_radius], end=[x1-off,mounting_pin_y-mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y+mount_pin_radius], end=[x1-off,mounting_pin_y+mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Arc(center=[lx2,mounting_pin_y], start=[lx2,mounting_pin_y-mount_pin_radius], angle=180, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y-mount_pin_radius], end=[x2+off,mounting_pin_y-mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y+mount_pin_radius], end=[x2+off,mounting_pin_y+mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) else: #add PCB locators boss_drill = 1.8 boss_x = (pins_per_row-1) * pitch + (3.48 if pins_per_row == 1 else 2.48) boss_y = row + 2.77 kicad_mod.append(Pad(at=[boss_x, boss_y],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) #draw the outline of the shape p1m_sl = 1 kicad_mod.append(PolygoneLine(polygone=[ {'x': body_edge['left'] + p1m_sl, 'y': body_edge['top']}, {'x': body_edge['left'], 'y': body_edge['top'] +p1m_sl}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['left'] + p1m_sl, 'y': body_edge['top']} ], layer='F.Fab', width=configuration['fab_line_width'])) #draw the outline of the tab kicad_mod.append(PolygoneLine(polygone=[ {'x': P/2 - tab_l/2,'y': y2}, {'x': P/2 - tab_l/2,'y': y2 + tab_w}, {'x': P/2 + tab_l/2,'y': y2 + tab_w}, {'x': P/2 + tab_l/2,'y': y2}, ], layer='F.Fab', width=configuration['fab_line_width'])) #draw the outline of the connector on the silkscreen outline = [ {'x': P/2,'y': y1-off}, {'x': x1-off,'y': y1-off}, {'x': x1-off,'y': y2+off}, {'x': P/2 - tab_l/2 - off,'y': y2+off}, {'x': P/2 - tab_l/2 - off,'y': y2 + off + tab_w}, {'x': P/2, 'y': y2 + off + tab_w}, ] kicad_mod.append(PolygoneLine(polygone=outline, layer='F.SilkS', width=configuration['silk_line_width'])) if variant_params[variant]['mount_pins']: kicad_mod.append(PolygoneLine(polygone=outline, x_mirror=P/2, layer='F.SilkS', width=configuration['silk_line_width'])) else: outline1 = outline[:2] outline1.append({'x': outline[2]['x'], 'y': boss_y - boss_drill/2 - silk_pad_off}) kicad_mod.append(PolygoneLine(polygone=outline1, x_mirror=P/2, layer='F.SilkS', width=configuration['silk_line_width'])) outline2 = outline[2:] outline2[0]['x'] = P - boss_x + boss_drill/2 + silk_pad_off # outline contains the mirrored version kicad_mod.append(PolygoneLine(polygone=outline2, x_mirror=P/2, layer='F.SilkS', width=configuration['silk_line_width'])) #draw square around each pin if draw_inner_details: for i in range(pins_per_row): for j in range(2): x = i * pitch y = j * row s = 0.4 * pitch kicad_mod.append(RectLine(start=[x-s,y-s],end=[x+s,y+s], layer='F.Fab', width=configuration['fab_line_width'])) #pin-1 marker p1m_off = 0.3 + off p1m_sl = 2 pin = [ {'x': body_edge['left'] - p1m_off,'y': body_edge['top'] + p1m_sl}, {'x': body_edge['left'] - p1m_off,'y': body_edge['top'] - p1m_off}, {'x': body_edge['left'] + p1m_sl,'y': body_edge['top'] - p1m_off}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if variant_params[variant]['mount_pins']: cx3 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx4 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) mount_pin_radius = (B/2 - C/2) cy3=roundToBase(mounting_pin_y - mount_pin_radius - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) poly_crtyd = [ {'x': cx3, 'y': cy1}, {'x': cx3, 'y': cy3}, {'x': cx1, 'y': cy3}, {'x': cx1, 'y': cy2}, {'x': cx2, 'y': cy2}, {'x': cx2, 'y': cy3}, {'x': cx4, 'y': cy3}, {'x': cx4, 'y': cy1}, {'x': cx3, 'y': cy1} ] kicad_mod.append(PolygoneLine(polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) else: kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-clasp_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "MicroClasp" series_long = 'MicroClasp Wire-to-Board System' manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 #pins_per_row_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row #with boss, suffix = 10 #no boss, suffix = 30 part = "55935-{n:02}{boss}" variant_params = { 'no_boss':{ 'boss': False, 'datasheet': 'http://www.molex.com/pdm_docs/sd/559350530_sd.pdf', 'part_code': "55935-{n:02}30", }, 'boss':{ 'boss': True, 'datasheet': 'http://www.molex.com/pdm_docs/sd/559350210_sd.pdf', 'part_code': "55935-{n:02}10", } } pitch = 2 drill = 0.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, variant, configuration): boss = variant_params[variant]['boss'] mpn = variant_params[variant]['part_code'].format(n=pins) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}{:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ", with PCB locator" if boss else '', pins, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions #B = distance between end-point pins B = (pins - 1) * pitch #A = total connector length A = B + 6 #C = internal length of connector C = B + 3 #T = length of tab if pins == 2: T = 5 else: T = 6.78 #corners x1 = -(A-B) / 2 x2 = x1 + A y2 = 9.2 y1 = y2 - 11.25 #y-pos of tab yt = y1 + 11.75 xt = B/2 - T/2 #y-pos backside yb = 0 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['bottom']=yt silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 out = [ {'x': B/2, 'y': yt}, {'x': xt+(yt-y2), 'y': yt}, {'x': xt, 'y': y2}, {'x': x1, 'y': y2}, {'x': x1, 'y': y1}, {'x': (B-C)/2, 'y': y1}, {'x': (B-C)/2, 'y': yb}, {'x': B/2,'y': yb} ] kicad_mod.append(PolygoneLine(polygone=out, layer="F.Fab", width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=out,x_mirror=B/2, layer="F.Fab", width=configuration['fab_line_width'])) #offset o = configuration['silk_fab_offset'] x1 -= o y1 -= o x2 += o y2 += o yt += o xt -= o out = [ {'x': B/2, 'y': yt}, {'x': xt+(yt-y2), 'y': yt}, {'x': xt, 'y': y2}, {'x': x1, 'y': y2}, {'x': x1, 'y': y1}, {'x': (B-C)/2+o, 'y': y1}, {'x': (B-C)/2+o, 'y': yb-o}, {'x': -pad_size[0]/2-silk_pad_off,'y': yb-o} ] kicad_mod.append(PolygoneLine(polygone=out, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=out,x_mirror=B/2, layer="F.SilkS", width=configuration['silk_line_width'])) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT #draw silkscreen inbetween pads for i in range(0,pins-1): xa = i * pitch + pad_size[0] / 2 + silk_pad_off xb = (i+1) * pitch - pad_size[0] / 2 - silk_pad_off kicad_mod.append(Line(start=[xa,yb-o],end=[xb,yb-o], layer='F.SilkS', width=configuration['silk_line_width'])) #generate the pads kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #add PCB locator if needed if boss: boss_x = B+2 boss_y = 2.4 boss_drill = 1.2 kicad_mod.append(Pad(at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) boss_x = -2 kicad_mod.append(Pad(at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) #pin-1 marker y = 3.5 m = 0.3 p1m_sl = 2 p1m_off = o + 0.3 pin = [ {'x': body_edge['left'] - p1m_off,'y': body_edge['top']+p1m_sl}, {'x': body_edge['left'] - p1m_off,'y': body_edge['top']-p1m_off}, {'x': body_edge['left'] + p1m_sl,'y': body_edge['top']-p1m_off}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) p1m_sl = 1 pin = [ {'x': -p1m_sl/2,'y': 0}, {'x': 0,'y': 0 + p1m_sl/sqrt(2)}, {'x': p1m_sl/2,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.Fab", width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-clasp_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "MicroClasp" series_long = 'MicroClasp Wire-to-Board System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 #pins_per_row_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row #with boss, suffix = 10 #no boss, suffix = 30 part = "55932-{n:02}{boss}" variant_params = { 'no_boss':{ 'boss': False, 'datasheet': 'http://www.molex.com/pdm_docs/sd/559320530_sd.pdf', 'part_code': "55932-{n:02}30", }, 'boss':{ 'boss': True, 'datasheet': 'http://www.molex.com/pdm_docs/sd/559320210_sd.pdf', 'part_code': "55932-{n:02}10", } } pitch = 2 drill = 0.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, variant, configuration): boss = variant_params[variant]['boss'] mpn = variant_params[variant]['part_code'].format(n=pins) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}{:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ", with PCB locator" if boss else '', pins, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions #B = distance between end-point pins B = (pins - 1) * pitch #A = total connector length A = B + 6 #C = internal length of connector C = B + 3 #T = length of tab if pins == 2: T = 5 else: T = 6.78 #wall-thickness w w = 0.6 #corners x1 = -(A-B) / 2 x2 = x1 + A y2 = 3 y1 = y2 - (6.3 if pins == 2 else 5.8) #y-pos of tab yt = y2 - 6.7 xt = B/2 - T/2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['top']=yt out = [ {'x': B/2, 'y': yt}, {'x': xt, 'y': yt}, {'x': xt, 'y': y1}, {'x': x1, 'y': y1}, {'x': x1, 'y': y2}, {'x': B/2, 'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=out, layer="F.Fab", width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=out,x_mirror=B/2, layer="F.Fab", width=configuration['fab_line_width'])) #offset o = configuration['silk_fab_offset'] x1 -= o y1 -= o x2 += o y2 += o yt -= o xt -= o out = [ {'x': B/2, 'y': yt}, {'x': xt, 'y': yt}, {'x': xt, 'y': y1}, {'x': x1, 'y': y1}, {'x': x1, 'y': y2}, {'x': B/2, 'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=out, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=out,x_mirror=B/2, layer="F.SilkS", width=configuration['silk_line_width'])) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT #generate the pads kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #add PCB locator if needed if boss: boss_x = B+2 boss_y = -1.9 boss_drill = 1.3 kicad_mod.append(Pad(at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) #draw the inner wall # Inner details are incorrect. I could not be bothered to fix them. # wall = [ # {'x': B/2, 'y': yt + 2*w}, # {'x': B/2 - pitch / 2, 'y': yt + 2*w}, # {'x': B/2 - pitch / 2, 'y': yt + w}, # {'x': B/2 - T/2 + w, 'y': yt + w}, # {'x': B/2 - T/2 + w, 'y': y1 + 2*w}, # {'x': -0.25, 'y': y1 + 2*w}, # {'x': -0.25, 'y': y1 + w}, # {'x': -(C-B)/2, 'y': y1 + w}, # {'x': -(C-B)/2, 'y': y2 - 3*w}, # {'x': x1+w, 'y': y2 - 3*w}, # {'x': x1+w, 'y': y2 - w}, # {'x': B/2, 'y': y2 - w}, # ] # # kicad_mod.append(PolygoneLine(polygone=wall, # layer="F.SilkS", width=configuration['silk_line_width'])) # kicad_mod.append(PolygoneLine(polygone=wall, x_mirror=B/2, # layer="F.SilkS", width=configuration['silk_line_width'])) #pin-1 marker y = 3.5 m = 0.3 p1m_sl = 2 p1m_off = o + 0.3 pin = [ {'x': body_edge['left'] - p1m_off,'y': body_edge['bottom']-p1m_sl}, {'x': body_edge['left'] - p1m_off,'y': body_edge['bottom']+p1m_off}, {'x': body_edge['left'] + p1m_sl,'y': body_edge['bottom']+p1m_off}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) p1m_sl = 1 pin = [ {'x': -p1m_sl/2,'y': body_edge['bottom']}, {'x': 0,'y': body_edge['bottom'] - p1m_sl/sqrt(2)}, {'x': p1m_sl/2,'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.Fab", width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-fit-3.0_smd_side_dual_row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Fit_3.0" series_long = 'Micro-Fit 3.0 Connector System' manufacturer = 'Molex' orientation = 'H' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/430450210_sd.pdf' #Molex part number #n = number of circuits per row part_code = "43045-{n:02}10" alternative_codes = [ "43045-{n:02}11", "43045-{n:02}09" ] pitch = 3.0 pincount_range = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] row = 5.5 pad_size = [1.27, 2.92] pitch_y = 1.71 + pad_size[1] mount_pad_size = [3.43, 1.65] def generate_one_footprint(pins, configuration): pins_per_row = pins//2 mpn = part_code.format(n=pins) alt_mpn = [code.format(n=pins) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "-1MP", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # Calculate dimensions if (pins < 4): B = 0 else: B = ((pins / 2) - 1) * pitch A = B + 6.65 C = B + 11.2 # D = pitch_y + PadSiseY pad_row_1_y = -pitch_y/2 pad_row_2_y = pad_row_1_y + pitch_y pad1_x = -B/2 mount_pad_x = ((C - mount_pad_size[0]) / 2) mount_pad_y = pad_row_1_y - (6.93 - pad_size[1]/2) body_edge={ 'left':-A/2, 'right':A/2, 'top': mount_pad_y - 4.6 } body_edge['bottom'] = body_edge['top'] + 9.91 # # Add solder nails # kicad_mod.append(Pad(at=[-mount_pad_x, mount_pad_y], number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=mount_pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(at=[mount_pad_x, mount_pad_y], number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=mount_pad_size, layers=Pad.LAYERS_SMT)) # # Add pads # kicad_mod.append(PadArray(start=[pad1_x, pad_row_1_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(start=[pad1_x, pad_row_2_y], initial=pins_per_row+1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) # # Add F.Fab # LayerA = ['F.Fab', 'F.SilkS', 'F.CrtYd'] LineDXA = [ 0, configuration['silk_fab_offset'], configuration['courtyard_offset']['connector'] ] LindeDeltaA = [0, configuration['silk_pad_clearance'] + configuration['silk_line_width']/2, 0] LineWidthA = [ configuration['fab_line_width'], configuration['silk_line_width'], configuration['courtyard_line_width'] ] gridA = [0, 0, configuration['courtyard_grid']] for i in range(0,3): LineDX = LineDXA[i] Layer = LayerA[i] LineWidth = LineWidthA[i] LindeDelta = LindeDeltaA[i] points = [] grid = gridA[i] x1 = 0 y1 = body_edge['top'] - LineDX points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (A / 2) - 1 + LineDX y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (A / 2) + LineDX y1 = y1 + 2 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = x1 y1 = mount_pad_y - ((mount_pad_size[1] / 2) + LineDX + LindeDelta) points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # if (i == 1): # SilkS kicad_mod.append(PolygoneLine(polygone=points, layer=Layer, width=LineWidth)) # # Need to do something ugly here, becosue we will do points = [] # We need to reflect these points already here # points2 = [] for pp in points: points2.append([-pp[0], pp[1]]) kicad_mod.append(PolygoneLine(polygone=points2, layer=Layer, width=LineWidth)) # # points = [] x1 = x1 y1 =mount_pad_y + ((mount_pad_size[1] / 2) + LineDX + LindeDelta) points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) elif (i == 2): # CrtYd x1 = mount_pad_x + (mount_pad_size[0] / 2) + LineDX y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = x1 y1 =mount_pad_y + ((mount_pad_size[1] / 2) + LineDX) points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (A / 2) + LineDX y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = x1 y1 = body_edge['bottom'] + LineDX points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # x1 = (B / 2) + (pad_size[0] / 2) + LineDX + LindeDelta y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # if (i == 0): x1 = 0 y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) if (i == 1): ttx1 = x1 tty1 = y1 + (pad_size[1] / 2) if (i == 2): x1 = x1 y1 = ((pitch_y / 2) + (pad_size[1] / 2) + LineDX) ttx1 = x1 tty1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # # x1 = 0 y1 = y1 points.append([roundToBase(x1, grid), roundToBase(y1, grid)]) # # Reflect right part around the X-axis # points2 = [] for pp in points: points2.append([0 - pp[0], pp[1]]) # # if (i == 0): # Fab # Add pin 1 marker tt = len(points2) ps = points2[tt - 1] p1 = points2[tt - 2] p2 = [(0 - (B / 2)) - 1, p1[1]] p3 = [(0 - (B / 2)), p1[1] - 1] p4 = [(0 - (B / 2)) + 1, p1[1]] points2[tt - 2] = p2 points2[tt - 1] = p3 points2.append(p4) points2.append(ps) elif (i == 1): # silk points2.append([roundToBase(0 - ttx1, grid), roundToBase(tty1, grid)]) # # kicad_mod.append(PolygoneLine(polygone=points, layer=Layer, width=LineWidth)) # kicad_mod.append(PolygoneLine(polygone=points2, layer=Layer, width=LineWidth)) ######################### Text Fields ############################### cy1 = roundToBase(body_edge['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(pad_row_2_y + pad_size[1]/2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pincount in pincount_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-fit-3.0_smd_top_dual_row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Fit_3.0" series_long = 'Micro-Fit 3.0 Connector System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 variant_params = { 'solder_mounting':{ 'mount_pins': 'solder', 'datasheet': 'http://www.molex.com/pdm_docs/sd/430450218_sd.pdf', 'C_minus_B': 11.2, 'part_code': "43045-{n:02}18", 'alternative_codes': [ "43045-{n:02}19", "43045-{n:02}20" ] }, 'retention_pin':{ 'mount_pins': 'npth', 'datasheet': 'http://www.molex.com/pdm_docs/sd/430450217_sd.pdf', 'C_minus_B': 4.3, 'part_code': "43045-{n:02}15", 'alternative_codes': [ "43045-{n:02}16", "43045-{n:02}17" ] } } pins_per_row_range = range(1,13) pitch = 3.0 pad_size = [1.27, 2.54] pitch_y = 6.86 + pad_size[1] mount_pad_size = [3.43, 1.65] mount_drill = 2.41 def generate_one_footprint(pins_per_row, variant, configuration): is_solder_mp = variant_params[variant]['mount_pins'] == 'solder' mpn = variant_params[variant]['part_code'].format(n=pins_per_row*2) alt_mpn = [code.format(n=pins_per_row*2) for code in variant_params[variant]['alternative_codes']] # handle arguments mp_name = "" if is_solder_mp: mp_name = "-1MP" orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = mp_name, pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') ########################## Dimensions ############################## B = (pins_per_row-1)*pitch A = B + 6.65 C = B + variant_params[variant]['C_minus_B'] pad_row_1_y = -pitch_y/2 pad_row_2_y = pad_row_1_y + pitch_y pad1_x = -B/2 mount_pad_x = C/2 - (mount_pad_size[0]/2 if is_solder_mp else 0) mount_pad_y = pad_row_1_y + pitch_y/2 tab_w = 1.4 tab_l = 1.4 body_edge={ 'left': -A/2, 'right': A/2, 'bottom': 3.43 } body_edge['top'] = body_edge['bottom'] - 6.87 chamfer={'x': 1.2, 'y': 0.63} y_top_min = body_edge['bottom'] - 7.37 bounding_box={ 'left': -C/2 if is_solder_mp else body_edge['left'], 'right': C/2 if is_solder_mp else body_edge['right'], 'top': pad_row_1_y - pad_size[1]/2, 'bottom': pad_row_2_y + pad_size[1]/2 } ############################# Pads ################################## if is_solder_mp: # # Add solder nails # kicad_mod.append(Pad(at=[-mount_pad_x, mount_pad_y], number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=mount_pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(at=[mount_pad_x, mount_pad_y], number=configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=mount_pad_size, layers=Pad.LAYERS_SMT)) else: kicad_mod.append(Pad(at=[-mount_pad_x, mount_pad_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[mount_pad_x, mount_pad_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=mount_drill, drill=mount_drill, layers=Pad.LAYERS_NPTH)) # # Add pads # kicad_mod.append(PadArray(start=[pad1_x, pad_row_1_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(start=[pad1_x, pad_row_2_y], initial=pins_per_row+1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': y_top_min}, {'x': body_edge['left'], 'y': y_top_min}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) kicad_mod.append(Line( start={ 'x': body_edge['left'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) kicad_mod.append(Line( start={ 'x': body_edge['right'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) tab_poly = [ {'x': -tab_l/2, 'y': body_edge['bottom']}, {'x': -tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': tab_l/2, 'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) p1m_sl = 1 p1m_poly = tab_poly = [ {'x': pad1_x - p1m_sl/2, 'y': body_edge['top']}, {'x': pad1_x, 'y': body_edge['top'] + p1m_sl/sqrt(2)}, {'x': pad1_x + p1m_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) ############################ SilkS ################################## # Top left corner silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 xp1_left = pad1_x - pad_size[0]/2 - silk_pad_off ymp_top = mount_pad_y - mount_pad_size[1]/2 - silk_pad_off ymp_bottom = mount_pad_y + mount_pad_size[1]/2 + silk_pad_off xpn_right = pad1_x + B + pad_size[0]/2 + silk_pad_off off = configuration['silk_fab_offset'] poly_s_bl = [ {'x': body_edge['left'] - off, 'y': ymp_bottom}, {'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off}, {'x': xp1_left, 'y': body_edge['bottom'] + off} ] kicad_mod.append(PolygoneLine(polygone=poly_s_bl, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_br = [ {'x': body_edge['right'] + off, 'y': ymp_bottom}, {'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off}, {'x': xpn_right, 'y': body_edge['bottom'] + off} ] kicad_mod.append(PolygoneLine(polygone=poly_s_br, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_tl = [ {'x': body_edge['left'] - off, 'y': ymp_top}, {'x': body_edge['left'] - off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': body_edge['top'] - off}, {'x': xp1_left, 'y': body_edge['top'] - off}, {'x': xp1_left, 'y': bounding_box['top']} ] kicad_mod.append(PolygoneLine(polygone=poly_s_tl, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_br = [ {'x': body_edge['right'] + off, 'y': ymp_top}, {'x': body_edge['right'] + off, 'y': y_top_min - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': y_top_min - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': body_edge['top'] - off}, {'x': xpn_right, 'y': body_edge['top'] - off} ] kicad_mod.append(PolygoneLine(polygone=poly_s_br, width=configuration['silk_line_width'], layer="F.SilkS")) ############################ CrtYd ################################## CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cy_top = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cy_body_top = roundToBase(y_top_min - CrtYd_offset, CrtYd_grid) cy_mp_top = roundToBase(mount_pad_y - mount_pad_size[1]/2 - CrtYd_offset, CrtYd_grid) cy_mp_bottom = roundToBase(mount_pad_y + mount_pad_size[1]/2 + CrtYd_offset, CrtYd_grid) cy_body_bottom = roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid) cy_bottom = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) cy_left = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy_body_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cy_pad_left = roundToBase(pad1_x - pad_size[0]/2 - CrtYd_offset, CrtYd_grid) cy_pad_right = roundToBase(pad1_x + B + pad_size[0]/2 + CrtYd_offset, CrtYd_grid) cy_body_right = roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid) cy_right = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) CrtYd_poly_t = [ {'x': pad1_x + B/2, 'y':cy_top}, {'x': cy_pad_left, 'y':cy_top}, {'x': cy_pad_left, 'y':cy_body_top}, {'x': cy_body_left, 'y':cy_body_top} ] CrtYd_poly_m = [ {'x': cy_body_left, 'y':cy_mp_top}, {'x': cy_left, 'y':cy_mp_top}, {'x': cy_left, 'y':cy_mp_bottom}, {'x': cy_body_left, 'y':cy_mp_bottom} ] CrtYd_poly_b = [ {'x': cy_body_left, 'y':cy_body_bottom}, {'x': cy_pad_left, 'y':cy_body_bottom}, {'x': cy_pad_left, 'y':cy_bottom}, {'x': pad1_x+B/2, 'y':cy_bottom} ] CrtYd_poly = CrtYd_poly_t if is_solder_mp: CrtYd_poly.extend(CrtYd_poly_m) CrtYd_poly.extend(CrtYd_poly_b) kicad_mod.append(PolygoneLine(polygone=CrtYd_poly, layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(PolygoneLine(polygone=CrtYd_poly, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror= 0.00000001 if pad1_x+B/2 == 0 else pad1_x+B/2)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy_top, 'bottom':cy_bottom}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-fit-3.0_tht_side_dual_row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Fit_3.0" series_long = 'Micro-Fit 3.0 Connector System' manufacturer = 'Molex' orientation = 'H' number_of_rows = 2 variants = {'non-clip': '0', 'clip': '2'} datasheet = 'https://www.molex.com/pdm_docs/sd/4304502{s}1_sd.pdf' #Molex part number #n = number of circuits per row part_code = "43045-{n:02}{s}{finish}" pins_per_row_range = range(1,13) pitch = 3.0 drill = 1.02 peg_drill = 3.0 clip_drill = 2.41 clip_pad = [clip_drill + 1, clip_drill + 1] pad_to_pad_clearance = 1.5 # Voltage rating is up to 600V (http://www.molex.com/pdm_docs/ps/PS-43045.pdf) pad_size = [pitch - pad_to_pad_clearance, pitch - pad_to_pad_clearance] def generate_one_footprint(pins, configuration, variant): pins_per_row = pins mpn = part_code.format(n=pins*2,s=variants[variant],finish=max(int(variants[variant]) - 1, 0)) alt_mpn = part_code.format(n=pins*2,s=variants[variant],finish='x') # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = '-1MP' if variant == 'clip' else "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (alternative finishes: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, alt_mpn, pins_per_row, datasheet.format(s=variants[variant]))) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) ########################## Dimensions ############################## B = (pins_per_row-1)*pitch A = B + 6.65 #Puts first pin on 0,0 and second row 0, pitch pad_row_1_y = 0 pad_row_2_y = pad_row_1_y + pitch pad1_x = 0 peg_clip_y_offset = 4.32 peg_x_offset = 2.16 clip_x_offset = -2.15 peg_C = 1.7 + pitch*(pins-3) #1º need be 4.7mm clip_C = 4.3 + pitch*(pins-1) body_edge={ 'left':-3.325-0.25, 'right':A-3.325+0.25, 'top': -12.24+3+0.64/2 } body_edge['bottom'] = body_edge['top'] + 9.91 bevel = 1 ############################# Pads ################################## # # Pegs # if variant == 'non-clip': if pins_per_row == 1: kicad_mod.append(Pad(at=[0, pad_row_1_y - peg_clip_y_offset], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) elif pins_per_row == 2: kicad_mod.append(Pad(at=[pitch/2, pad_row_1_y - peg_clip_y_offset], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) elif pins_per_row == 3: kicad_mod.append(Pad(at=[pitch, pad_row_1_y - peg_clip_y_offset], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) else: kicad_mod.append(Pad(at=[pad1_x + peg_x_offset, pad_row_1_y - peg_clip_y_offset], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[pad1_x + peg_x_offset + peg_C, pad_row_1_y - peg_clip_y_offset], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) elif variant == 'clip': kicad_mod.append(Pad(at=[pad1_x + clip_x_offset, pad_row_1_y - peg_clip_y_offset], number="MP", type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, size=clip_pad, drill=clip_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[pad1_x + clip_x_offset + clip_C, pad_row_1_y - peg_clip_y_offset], number="MP", type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, size=clip_pad, drill=clip_drill, layers=Pad.LAYERS_THT)) # # Add pads # optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[pad1_x, pad_row_1_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) kicad_mod.append(PadArray(start=[pad1_x, pad_row_2_y], initial=pins_per_row+1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) ######################## Clip copper keepout ########################### if variant == 'clip': keepout_width = 2.45 keepout_height = 1.6 keepout_center_x = [body_edge['left'] - 0.75 + keepout_width / 2, body_edge['right'] + 0.75 - keepout_width / 2] keepout_center_y = body_edge['bottom'] - 3.25 + keepout_height / 2 keepout_text = 'CU KEEPOUT' keepout_text_width = keepout_width / len(keepout_text) keepout_text_thickness = keepout_text_width * 0.15 kicad_mod.append(PolygoneLine(polygone=[[keepout_center_x[0] - keepout_width/2, keepout_center_y - keepout_height/2], [keepout_center_x[0] - keepout_width/2, keepout_center_y + keepout_height/2], [keepout_center_x[0] + keepout_width/2, keepout_center_y + keepout_height/2], [keepout_center_x[0] + keepout_width/2, keepout_center_y - keepout_height/2], [keepout_center_x[0] - keepout_width/2, keepout_center_y - keepout_height/2]], layer='Dwgs.User', width=0.1)) kicad_mod.append(PolygoneLine(polygone=[[keepout_center_x[1] - keepout_width/2, keepout_center_y - keepout_height/2], [keepout_center_x[1] - keepout_width/2, keepout_center_y + keepout_height/2], [keepout_center_x[1] + keepout_width/2, keepout_center_y + keepout_height/2], [keepout_center_x[1] + keepout_width/2, keepout_center_y - keepout_height/2], [keepout_center_x[1] - keepout_width/2, keepout_center_y - keepout_height/2]], layer='Dwgs.User', width=0.1)) kicad_mod.append(Text(type='user', text='CU KEEPOUT', at=[keepout_center_x[0], keepout_center_y], layer='Cmts.User', size=[keepout_text_width, keepout_text_width], thickness=keepout_text_thickness)) kicad_mod.append(Text(type='user', text='CU KEEPOUT', at=[keepout_center_x[1], keepout_center_y], layer='Cmts.User', size=[keepout_text_width, keepout_text_width], thickness=keepout_text_thickness)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top'] + bevel}, {'x': body_edge['left'] + bevel, 'y': body_edge['top']}, {'x': body_edge['right'] - bevel, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top'] + bevel}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_arrow_poly= [ {'x': -.75, 'y': body_edge['bottom']}, {'x': 0, 'y': 0}, {'x': 0.75, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_arrow_poly, width=configuration['fab_line_width'], layer="F.Fab")) ######################## SilkS Layer ########################### if variant == 'non-clip': poly_s_t= [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['top'] + bevel - configuration['silk_fab_offset']}, {'x': body_edge['left'] + bevel - configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] - bevel + configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['top'] + bevel - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) if variant == 'clip': # top side (away from pins) poly_s_t= [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': pad_row_1_y - peg_clip_y_offset - clip_pad[1]/2 + configuration['silk_fab_offset']}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['top'] + bevel - configuration['silk_fab_offset']}, {'x': body_edge['left'] + bevel - configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] - bevel + configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['top'] + bevel - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': pad_row_1_y - peg_clip_y_offset - clip_pad[1]/2 + configuration['silk_fab_offset']}, #{'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) # bottom side (closest to pins) poly_s_t= [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': pad_row_1_y - peg_clip_y_offset + clip_pad[1]/2 - configuration['silk_fab_offset']}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, #{'x': body_edge['left'] + bevel - configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, #{'x': body_edge['right'] - bevel + configuration['silk_fab_offset'], 'y': body_edge['top'] - configuration['silk_fab_offset']}, #{'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['top'] + bevel - configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': pad_row_1_y - peg_clip_y_offset + clip_pad[1]/2 - configuration['silk_fab_offset']} #{'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': body_edge['bottom'] + configuration['silk_fab_offset']}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) ######################## CrtYd Layer ########################### CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] CrtYd_left = pad1_x + clip_x_offset - clip_pad[0]/2 if variant == 'clip' else body_edge['left'] CrtYd_right = pad1_x + clip_x_offset + clip_C + clip_pad[0]/2 if variant == 'clip' else body_edge['right'] poly_yd = [ {'x': roundToBase(CrtYd_left - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(CrtYd_left - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['top'] - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(CrtYd_right + CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['top'] - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(CrtYd_right + CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(B + pad_to_pad_clearance/2 + CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(B + pad_to_pad_clearance/2 + CrtYd_offset, CrtYd_grid), 'y': roundToBase(pitch + pad_to_pad_clearance/2 + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(- pad_to_pad_clearance/2 - CrtYd_offset, CrtYd_grid), 'y': roundToBase(pitch + pad_to_pad_clearance/2 + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(- pad_to_pad_clearance/2 - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(CrtYd_left - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)} ] kicad_mod.append(PolygoneLine(polygone=poly_yd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### cy1 = roundToBase(body_edge['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(pad_row_2_y + pad_size[1] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Write to File and 3D ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pins_per_row_range: for variant in variants: generate_one_footprint(pincount, configuration, variant) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-fit-3.0_tht_side_single_row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Fit_3.0" series_long = 'Micro-Fit 3.0 Connector System' manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 datasheet = 'https://www.molex.com/pdm_docs/sd/436500300_sd.pdf' #Molex part number #n = number of circuits per row part_code = "43650-{n:02}00" alternative_codes = [ "43650-{n:02}01", "43650-{n:02}02" ] pins_per_row_range = range(2,13) pitch = 3.0 drill = 1.02 peg_drill = 3.0 pad_to_pad_clearance = 1.5 # Voltage rating is up to 600V (http://www.molex.com/pdm_docs/ps/PS-43045.pdf) max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, configuration): pins_per_row = pins mpn = part_code.format(n=pins) alt_mpn = [code.format(n=pins) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) ########################## Dimensions ############################## B = (pins_per_row-1)*pitch A = B + 6.65 #Centra os pinos em metade do pitch pad_row_1_y = 0 pad_row_2_y = pad_row_1_y + pitch pad1_x = 0 C = 1.7 + pitch*(pins-3) #1º need be 4.7mm body_edge={ 'left':-3.325, 'right':A-3.325, 'top': -8.92 } body_edge['bottom'] = body_edge['top'] + 9.90 ############################# Pads ################################## # # Pegs # if pins_per_row == 2: kicad_mod.append(Pad(at=[pitch/2, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) elif pins_per_row == 3: kicad_mod.append(Pad(at=[pitch, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) else: kicad_mod.append(Pad(at=[pad1_x + 2.15, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[pad1_x + 2.15 + C, pad_row_1_y - 4.32], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) # # Add pads # optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[pad1_x, pad_row_1_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']+1}, {'x': body_edge['left']+1, 'y': body_edge['top']}, {'x': body_edge['right']-1, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']+1}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) main_arrow_poly= [ {'x': -.75, 'y': body_edge['bottom']}, {'x': 0, 'y': 0}, {'x': 0.75, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=main_arrow_poly, width=configuration['fab_line_width'], layer="F.Fab")) ######################## SilkS Layer ########################### off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_line_width']/2 + configuration['silk_pad_clearance'] r_no_silk = max(pad_size)/2 + pad_silk_off # simplified to circle instead of oval dy = abs(body_edge['bottom']) + off pin_center_silk_x = 0 if dy >= r_no_silk else sqrt(r_no_silk**2-dy**2) pin1_center_silk_x = pad_size[0]/2 + pad_silk_off # simplified to rectangle instead of rounded rect poly_s_t= [ {'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off}, {'x': body_edge['left'] - off, 'y': body_edge['top'] + 1 - off}, {'x': body_edge['left'] + 1 - off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - 1 + off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] + off, 'y': body_edge['top'] + 1 - off}, {'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off} ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) if pin_center_silk_x == 0: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['bottom']], end=[body_edge['right']-off, body_edge['bottom']], layer="F.SilkS", width=configuration['silk_line_width'] )) else: kicad_mod.append(Line( start=[body_edge['left']-off, body_edge['bottom']+off], end=[-pin1_center_silk_x, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[body_edge['right']+off, body_edge['bottom']+off], end=[(pins_per_row-1)*pitch + pin_center_silk_x, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) kicad_mod.append(Line( start=[pin1_center_silk_x, body_edge['bottom']+off], end=[pitch - pin_center_silk_x, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) for i in range(1, pins_per_row-1): xl = i*pitch + pin_center_silk_x xr = (i+1)*pitch - pin_center_silk_x kicad_mod.append(Line( start=[xl, body_edge['bottom']+off], end=[xr, body_edge['bottom']+off], layer="F.SilkS", width=configuration['silk_line_width'] )) ######################## CrtYd Layer ########################### CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] poly_yd = [ {'x': roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['top'] - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['top'] - CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)}, {'x': roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid), 'y': roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid)} ] kicad_mod.append(PolygoneLine(polygone=poly_yd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### cy1 = roundToBase(body_edge['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(pad_size[1] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Write to File and 3D ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pins_per_row_range: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-fit-3.0_tht_top_dual_row.py ================================================ #!/usr/bin/env python ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Fit_3.0" series_long = 'Micro-Fit 3.0 Connector System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 variant_params = { 'solder_mounting':{ 'mount_pins': 'solder', # remove this 'datasheet': 'http://www.molex.com/pdm_docs/sd/430450212_sd.pdf', 'C_minus_B': 6, 'part_code': "43045-{n:02}12", 'alternative_codes': [ "43045-{n:02}13", "43045-{n:02}24" ] }, } pins_per_row_range = range(1,13) pitch = 3.0 drill = 1.02 peg_drill = 1.02 pad_to_pad_clearance = 1.5 # Voltage rating is up to 600V (http://www.molex.com/pdm_docs/ps/PS-43045.pdf) max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, pitch - pad_to_pad_clearance] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, variant, configuration): mpn = variant_params[variant]['part_code'].format(n=pins_per_row*number_of_rows) alt_mpn = [code.format(n=pins_per_row*number_of_rows) for code in variant_params[variant]['alternative_codes']] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #kicad_mod.setAttribute('smd') ########################## Dimensions ############################## B = (pins_per_row-1)*pitch A = B + 6.65 C = B + variant_params[variant]['C_minus_B'] pad_row_1_y = 0 pad1_x = 0 peg1_x = (B-C)/2 peg2_x = (B+C)/2 peg_y = pad_row_1_y + pitch + 0.94 tab_w = 1.4 tab_l = 1.4 body_edge={ 'left': (B-A)/2, 'right': (A+B)/2, 'top': -2.47+0.5 } body_edge['bottom'] = body_edge['top'] + (7.37-0.5) y_top_min = -2.47 chamfer={'x': 1.2, 'y': 0.63} ############################# Pads ################################## # # Pegs # kicad_mod.append(Pad(at=[peg1_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[peg2_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) # # Add pads # optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( start=[pad1_x, pad_row_1_y+pitch*row_idx], initial=row_idx*pins_per_row+1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': y_top_min}, {'x': body_edge['left'], 'y': y_top_min}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) kicad_mod.append(Line( start={ 'x': body_edge['left'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) kicad_mod.append(Line( start={ 'x': body_edge['right'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) tab_poly = [ {'x': B/2-tab_l/2, 'y': body_edge['bottom']}, {'x': B/2-tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': B/2+tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': B/2+tab_l/2, 'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) p1m_sl = 1 p1m_poly = tab_poly = [ {'x': pad1_x - p1m_sl/2, 'y': body_edge['top']}, {'x': pad1_x, 'y': body_edge['top'] + p1m_sl/sqrt(2)}, {'x': pad1_x + p1m_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) ############################ SilkS ################################## # Top left corner silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 ymp_top = peg_y - peg_drill/2 - silk_pad_off ymp_bottom = peg_y + peg_drill/2 + silk_pad_off off = configuration['silk_fab_offset'] poly_s_b = [ {'x': body_edge['left'] - off, 'y': ymp_bottom}, {'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off}, {'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off}, {'x': body_edge['right'] + off, 'y': ymp_bottom}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_b, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_t = [ {'x': body_edge['left'] - off, 'y': ymp_top}, {'x': body_edge['left'] - off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': y_top_min - off}, {'x': body_edge['right'] + off, 'y': y_top_min - off}, {'x': body_edge['right'] + off, 'y': ymp_top}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) ############################ CrtYd ################################## CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cy_top = roundToBase(y_top_min - CrtYd_offset, CrtYd_grid) cy_bottom = roundToBase(body_edge['bottom'] + tab_w + CrtYd_offset, CrtYd_grid) cy_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cy_right = roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid) poly_cy = [ {'x': cy_left, 'y':cy_top}, {'x': cy_right, 'y':cy_top}, {'x': cy_right, 'y':cy_bottom}, {'x': cy_left, 'y':cy_bottom}, {'x': cy_left, 'y':cy_top}, ] kicad_mod.append(PolygoneLine(polygone=poly_cy, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy_top, 'bottom':cy_bottom}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-fit-3.0_tht_top_single_row.py ================================================ #!/usr/bin/env python ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Fit_3.0" series_long = 'Micro-Fit 3.0 Connector System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 variant_params = { 'solder_mounting':{ 'mount_pins': 'solder', # remove this 'datasheet': 'http://www.molex.com/pdm_docs/sd/436500215_sd.pdf', 'C_minus_B': 6, 'part_code': "43650-{n:02}15", 'alternative_codes': [ "43650-{n:02}16", "43650-{n:02}17" ] }, } pins_per_row_range = range(2,13) pitch = 3.0 drill = 1.02 peg_drill = 1.27 pad_to_pad_clearance = 1.5 # Voltage rating is up to 600V (http://www.molex.com/pdm_docs/ps/PS-43650.pdf) max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, variant, configuration): mpn = variant_params[variant]['part_code'].format(n=pins_per_row*number_of_rows) alt_mpn = [code.format(n=pins_per_row*number_of_rows) for code in variant_params[variant]['alternative_codes']] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #kicad_mod.setAttribute('smd') ########################## Dimensions ############################## B = (pins_per_row-1)*pitch A = B + 6.65 C = B + variant_params[variant]['C_minus_B'] pad_y = 0 pad1_x = 0 peg1_x = (B-C)/2 peg2_x = (B+C)/2 peg_y = pad_y - 1.96 tab_w = 1.4 tab_l = 1.4 body_edge={ 'left': (B-A)/2, 'right': (A+B)/2, 'top': -2.47+0.5 } body_edge['bottom'] = body_edge['top'] + (4.37-0.5) y_top_min = -2.47 chamfer={'x': 1.2, 'y': 0.63} ############################# Pads ################################## # # Pegs # kicad_mod.append(Pad(at=[peg1_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[peg2_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) # # Add pads # optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[pad1_x, pad_y], initial=1, pincount=pins_per_row, increment=1, x_spacing=pitch, size=pad_size, type=Pad.TYPE_THT, shape=pad_shape, layers=Pad.LAYERS_THT, drill=drill, **optional_pad_params)) ######################## Fabrication Layer ########################### main_body_poly= [ {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': y_top_min}, {'x': body_edge['left'], 'y': y_top_min}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['right'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': y_top_min}, {'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top']}, {'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=main_body_poly, width=configuration['fab_line_width'], layer="F.Fab")) kicad_mod.append(Line( start={ 'x': body_edge['left'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['left'] + chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) kicad_mod.append(Line( start={ 'x': body_edge['right'], 'y': body_edge['top'] + chamfer['y'] }, end={ 'x': body_edge['right'] - chamfer['x'], 'y': body_edge['top'] }, width=configuration['fab_line_width'], layer="F.Fab" )) tab_poly = [ {'x': B/2-tab_l/2, 'y': body_edge['bottom']}, {'x': B/2-tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': B/2+tab_l/2, 'y': body_edge['bottom'] + tab_w}, {'x': B/2+tab_l/2, 'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) p1m_sl = 1 p1m_poly = tab_poly = [ {'x': pad1_x - p1m_sl/2, 'y': body_edge['top']}, {'x': pad1_x, 'y': body_edge['top'] + p1m_sl/sqrt(2)}, {'x': pad1_x + p1m_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=tab_poly, width=configuration['fab_line_width'], layer="F.Fab")) ############################ SilkS ################################## # Top left corner silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 xmp_top1 = peg1_x + peg_drill/2 + silk_pad_off xmp_top2 = peg2_x - peg_drill/2 - silk_pad_off ymp_bottom = peg_y + peg_drill/2 + silk_pad_off off = configuration['silk_fab_offset'] poly_s_b = [ {'x': body_edge['left'] - off, 'y': ymp_bottom}, {'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off}, {'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off}, {'x': body_edge['right'] + off, 'y': ymp_bottom}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_b, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_t = [ {'x': xmp_top1 + off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': y_top_min - off}, {'x': body_edge['left'] + chamfer['x'] + off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': body_edge['top'] - off}, {'x': body_edge['right'] - chamfer['x'] - off, 'y': y_top_min - off}, {'x': xmp_top2 - off, 'y': y_top_min - off}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) ############################ CrtYd ################################## CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cy_top = roundToBase(y_top_min - CrtYd_offset, CrtYd_grid) cy_bottom = roundToBase(body_edge['bottom'] + tab_w + CrtYd_offset, CrtYd_grid) cy_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cy_right = roundToBase(body_edge['right'] + CrtYd_offset, CrtYd_grid) poly_cy = [ {'x': cy_left, 'y':cy_top}, {'x': cy_right, 'y':cy_top}, {'x': cy_right, 'y':cy_bottom}, {'x': cy_left, 'y':cy_bottom}, {'x': cy_left, 'y':cy_top}, ] kicad_mod.append(PolygoneLine(polygone=poly_cy, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy_top, 'bottom':cy_bottom}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-latch_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Latch" series_long = 'Micro-Latch Wire-to-Board Connector System' manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/532530770_sd.pdf' #pins_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row part_code = "53254-{n:02d}70" alternative_codes = [ "53254-{n:02d}50" ] pitch = 2 drill = 0.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n=pins_per_row*number_of_rows) alt_mpn = [code.format(n=pins_per_row*number_of_rows) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins_per_row - 1) * pitch B = A + 3.1 C = A + 4 #connector thickness T = 5.75 #corners x1 = -2 x2 = x1 + C y1 = -6 y2 = y1 + 7.3 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() #add simple outline to F.Fab layer kicad_mod.append(RectLine(start=[x1,y1], end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) #wall-thickness W w = 0.45 #offset o = configuration['silk_fab_offset'] pso = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 x1 -= o y1 -= o x2 += o y2 += o #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins_per_row, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the connector outline out = [ {'x': -0.3,'y': pad_size[1]/2+pso}, {'x': -0.5,'y': y2}, {'x': x1+0.6,'y': y2}, {'x': x1+0.1,'y': 0.5}, {'x': x1+0.1,'y': 0}, {'x': x1,'y': 0}, {'x': x1,'y': y1}, {'x': A/2,'y': y1}, ] kicad_mod.append(PolygoneLine(polygone=out, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine(polygone=out,x_mirror=A/2, width=configuration['silk_line_width'], layer="F.SilkS")) #draw the pin tab bits for i in range(pins_per_row-1): x = i * pitch tab = [ {'x': x-0.3,'y': pad_size[1]/2+pso}, {'x': x+0.3,'y': pad_size[1]/2+pso}, {'x': x+0.5,'y': y2}, {'x': x+pitch-0.5,'y': y2}, {'x': x+pitch-0.3,'y': pad_size[1]/2+pso}, ] kicad_mod.append(PolygoneLine(polygone=tab, width=configuration['silk_line_width'], layer="F.SilkS")) #add the final tab line x = (pins_per_row-1) * pitch kicad_mod.append(Line(start=[x - 0.3, pad_size[1]/2+pso], end=[x+0.3, pad_size[1]/2+pso])) #pin-1 marker y = y2 + 0.5 m = 0.3 L = 2 O = 0.3 pin = [ {'x': x1 + L, 'y': y2 + O}, {'x': x1 - O, 'y': y2 + O}, {'x': x1 - O, 'y': y2 - L}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer="F.SilkS")) p1m_sl = 1 pin =[ {'x': -p1m_sl/2, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom'] - p1m_sl/sqrt(2)}, {'x': p1m_sl/2, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) #wall wall = [ {'x': x1+w,'y': y1}, {'x': x1+w,'y': -2.1}, {'x': x2-w,'y': -2.1}, {'x': x2-w,'y': y1}, ] kicad_mod.append(PolygoneLine(polygone=wall, width=configuration['silk_line_width'], layer="F.SilkS")) #draw each pin for i in range(pins_per_row): x = i * pitch ya = -2.1 yb = ya - 3.3 pin = [ {'x': x-0.25,'y': ya}, {'x': x-0.25,'y': yb + 0.25}, {'x': x,'y': yb}, {'x': x+0.25,'y': yb + 0.25}, {'x': x+0.25,'y': ya}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer="F.SilkS")) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_micro-latch_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Micro-Latch" series_long = 'Micro-Latch Wire-to-Board Connector System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/532530770_sd.pdf' #pins_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row part_code = "53253-{n:02d}70" alternative_codes = [ "53253-{n:02d}50" ] pitch = 2 drill = 0.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, configuration): mpn = part_code.format(n=pins_per_row*number_of_rows) alt_mpn = [code.format(n=pins_per_row*number_of_rows) for code in alternative_codes] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions A = (pins_per_row - 1) * pitch B = A + 3.1 C = A + 4 #connector thickness T = 5.75 #corners x1 = -2 x2 = x1 + C T = 3.65 y1 = -1.5 y2 = y1 + T off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() #add simple outline to F.Fab layer kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab', width=configuration['fab_line_width'])) #wall-thickness W w = 0.4 #offset o = configuration['silk_fab_offset'] x1 -= o y1 -= o x2 += o y2 += o #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray( pincount=pins_per_row, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #draw the courtyard #draw the connector outline out = RectLine(start=[x1,y1], end=[x2,y2], width=configuration['silk_line_width'], layer="F.SilkS") kicad_mod.append(out) #pin-1 marker y = -2 m = 0.3 O = 0.3 L = 2 pin = [ {'x': x1 + L, 'y': y1 - O}, {'x': x1 - O, 'y': y1 - O}, {'x': x1 - O, 'y': y1 + L}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer="F.SilkS")) p1m_sl = 1 pin =[ {'x': -p1m_sl/2, 'y': body_edge['top']}, {'x': 0, 'y': body_edge['top'] + p1m_sl/sqrt(2)}, {'x': p1m_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) kicad_mod.append(Line(start=[x1,2*w],end=[x1+w,2*w], width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(Line(start=[x2,2*w],end=[x2-w,2*w], width=configuration['silk_line_width'], layer="F.SilkS")) #add the 'wall' wall = [ {'x': A/2,'y': y1+w}, {'x': x1+w,'y': y1+w}, {'x': x1+w,'y': 0}, {'x': x1+2*w,'y': 0}, {'x': x1+2*w,'y': w}, {'x': x1+w,'y': w}, {'x': x1+w,'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=wall, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine(polygone=wall,x_mirror=A/2, width=configuration['silk_line_width'], layer="F.SilkS")) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_mini-fit-sr_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Mini-Fit_Sr" series_long = 'Mini-Fit Sr. Power Connectors' manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/428202214_sd.pdf' #pins_per_row per row pins_per_row_range = [2, 3, 4, 5, 6] #Molex part number #n = number of circuits per row part_code = "42820-{n}2XX" pitch = 10 drill = 2.8 offset_second_pad = 5 pad_to_pad_clearance = 3 max_annular_ring = 1 min_annular_ring = 0.15 #locating pins ret_dy = 5.73 ret_dx = 9.00 + offset_second_pad ret_drill = 3.00 ret_size = 4.00 pad_size = [offset_second_pad + 0.1, pitch - pad_to_pad_clearance] if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring version_params = { 'with_thermals':{ 'description': ', With thermal vias in pads', 'fp_name_suffix': '_ThermalVias', 'thermals': True }, 'only_pads':{ 'description': '', 'fp_name_suffix': '', 'thermals': False } } def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = part_code.format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # Dimensions P = (pins - 1) * pitch B = pins * pitch + 0.90 # connector length W = 21.00 # connector width tab_side_w = 1.46 yt1 = 0 - (B - P) / 2 # left yt2 = yt1 - tab_side_w yb1 = P + (B - P) / 2 # right yb2 = yb1 + tab_side_w xr1 = ret_dx + 13.56 # bottom xl1 = xr1 - W # top xl2 = xl1 - 7.6 body_edge={ 'left':xl1, 'right':xr1, 'bottom':yb1, 'top': yt1 } bounding_box = { 'top': -(ret_dy + ret_size/2), 'bottom': P + (ret_dy + ret_size/2), 'left': -pad_size[0]/2, 'right': body_edge['right'] } ################################## Pins ################################## for row_idx in range(2): kicad_mod.append(PadArray(pincount=pins, start=[row_idx*offset_second_pad, 0], y_spacing=pitch, size=pad_size, drill=drill, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT, tht_pad1_shape=Pad.SHAPE_RECT)) d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for yi in range(pins): n = yi + 1 pad_center_x = offset_second_pad/2 pad_center_y = yi*pitch pad_l = offset_second_pad + pad_size[0] dy = (pad_size[1] - 2*thermal_to_pad_edge)/2 dx = (pad_l - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, x_spacing=dx*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y - dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y + dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[ret_dx, -ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[ret_dx, P+ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -pad_size[1]/2], end=[offset_second_pad + pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) ############################ Outline ############################## #kicad_mod.append(RectLine(start=[xl1, yt1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine(start=[xl1, yt2], end=[xr1, yb2], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[xl1, yt1], end=[xr1, yt1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[xl1, yb1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) off = configuration['silk_fab_offset'] silk1 = [ {'y': -pad_size[1]/2 - pad_silk_off, 'x': xl1-off}, {'y': yt2-off, 'x': xl1-off}, {'y': yt2-off, 'x': ret_dx-ret_size/2}, ] kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'], y_mirror=P/2)) silk2 = [ {'y': yt2-off, 'x': ret_dx+ret_size/2}, {'y': yt2-off, 'x': xr1+off}, {'y': P/2, 'x': xr1+off}, ] kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'], y_mirror=P/2)) for i in range(pins - 1): kicad_mod.append(Line(start=[xl1-off, i*pitch+pad_size[1]/2+pad_silk_off], end=[xl1-off, (i+1)*pitch-pad_size[1]/2-pad_silk_off], layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins): w_pin = 3.8 kicad_mod.append(RectLine(start=[xl1, i*pitch-w_pin/2], end=[xl2, i*pitch+w_pin/2], layer='F.Fab', width=configuration['fab_line_width'])) ############################ Pin 1 ################################ # Pin 1 designator pin1_sl = 2.4 pin1 = [ {'x': body_edge['left'], 'y': -pin1_sl/2}, {'x': body_edge['left'] - pin1_sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': pin1_sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'], x_mirror=(body_edge['left']+xl2)/2)) pin1 = [ {'y': -pad_size[1]/2 - pad_silk_off, 'x': xl1-off}, {'y': -pad_size[1]/2 - pad_silk_off, 'x': -pad_size[0]/2} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) # pin1 = [ # {'x': 0, 'y': 8}, # {'x': 0.5, 'y': 9}, # {'x': -0.5, 'y': 9}, # {'x': 0, 'y': 8}, # ] # kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for version in version_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, version_params[version], configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_mini-fit-sr_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Mini-Fit_Sr" series_long = 'Mini-Fit Sr. Power Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/428192214_sd.pdf' #pins_per_row per row pins_per_row_range = [2, 3, 4, 5, 6] #Molex part number #n = number of circuits per row part_code = "42819-{n}2XX" pitch = 10 drill = 2.8 offset_second_pad = 4.4 pad_to_pad_clearance = 3 max_annular_ring = 1 min_annular_ring = 0.15 #locating pins ret_dy = 5.73 ret_dx = offset_second_pad - 0.35 ret_drill = 3.00 ret_size = 4.00 pad_size = [offset_second_pad + 0.1, pitch - pad_to_pad_clearance] if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring version_params = { 'with_thermals':{ 'description': ', With thermal vias in pads', 'fp_name_suffix': '_ThermalVias', 'thermals': True }, 'only_pads':{ 'description': '', 'fp_name_suffix': '', 'thermals': False } } def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = part_code.format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # Dimensions P = (pins - 1) * pitch B = pins * pitch + 0.90 # connector length W = 9.2 # connector width tab_side_w = 1.46 lock_tab_w1 = 1.8 lock_tab_w2 = 3.3 - lock_tab_w1 yt1 = 0 - (B - P) / 2 # left yt2 = yt1 - tab_side_w yb1 = P + (B - P) / 2 # right yb2 = yb1 + tab_side_w xl1 = -1.34 # bottom xr1 = xl1 + W # top xr2 = xl1 + 10.80 body_edge={ 'left':xl1, 'right':xr1, 'bottom':yb1, 'top': yt1 } bounding_box = { 'top': -(ret_dy + ret_size/2), 'bottom': P + (ret_dy + ret_size/2), 'left': body_edge['left'] - (lock_tab_w1 + lock_tab_w2), 'right': body_edge['right'] } ################################## Pins ################################## for pin_idx in range(2): kicad_mod.append(PadArray( pincount=pins, start=[pin_idx*offset_second_pad, 0], y_spacing=pitch, size=pad_size, drill=drill, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT, tht_pad1_shape=Pad.SHAPE_RECT)) d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for yi in range(pins): n = yi + 1 pad_center_x = offset_second_pad/2 pad_center_y = yi*pitch pad_l = offset_second_pad + pad_size[0] dy = (pad_size[1] - 2*thermal_to_pad_edge)/2 dx = (pad_l - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, x_spacing=dx*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y - dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y + dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[ret_dx, -ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[ret_dx, P+ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -pad_size[1]/2], end=[offset_second_pad + pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) ############################ Outline ############################## #kicad_mod.append(RectLine(start=[xl1, yt1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine(start=[xl1, yt2], end=[xr1, yb2], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[xl1, yt1], end=[xr1, yt1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[xl1, yb1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) off = configuration['silk_fab_offset'] silk1 = [ {'y': -pad_size[1]/2 - pad_silk_off, 'x': xl1-off}, {'y': yt2-off, 'x': xl1-off}, {'y': yt2-off, 'x': ret_dx-ret_size/2}, ] kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'], y_mirror=P/2)) silk2 = [ {'y': yt2-off, 'x': ret_dx+ret_size/2}, {'y': yt2-off, 'x': xr1+off}, {'y': P/2, 'x': xr1+off}, ] kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'], y_mirror=P/2)) for i in range(pins - 1): kicad_mod.append(Line(start=[xl1-off, i*pitch+pad_size[1]/2+pad_silk_off], end=[xl1-off, (i+1)*pitch-pad_size[1]/2-pad_silk_off], layer='F.SilkS', width=configuration['silk_line_width'])) # Flanges for i in range(pins): yt = i * pitch - 1.6 / 2 yb = i * pitch + 1.6 / 2 # kicad_mod.append(RectLine(start=[xr1, yt], end=[xr2, yb], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[ {'x': xr1, 'y': yt}, {'x': xr2, 'y': yt}, {'x': xr2, 'y': yb}, {'x': xr1, 'y': yb}, ], layer='F.Fab', width=configuration['fab_line_width'])) # kicad_mod.append(RectLine(start=[xr1+off, yt-off], end=[xr2+off, yb+off], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=[ {'x': xr1+off, 'y': yt-off}, {'x': xr2+off, 'y': yt-off}, {'x': xr2+off, 'y': yb+off}, {'x': xr1+off, 'y': yb+off}, ], layer='F.SilkS', width=configuration['silk_line_width'])) tab_l = 3.60 # tab length #tab_w = 3.30 # tab width xl2 = xl1 - lock_tab_w1 xl3 = xl2 - lock_tab_w2 yt4 = P / 2 - tab_l / 2 # left yb4 = P / 2 + tab_l / 2 # right if pins % 2: kicad_mod.append(RectLine(start=[xl1, yt4], end=[xl3, yb4], layer='F.Fab', width=configuration['fab_line_width'])) else: yt3 = (pins // 2 - 1) * pitch yb3 = (pins // 2) * pitch kicad_mod.append(RectLine(start=[xl1, yt3], end=[xl2, yb3], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine(start=[xl2, yt4], end=[xl3, yb4], layer='F.Fab', width=configuration['fab_line_width'])) tab = [ {'x': xl2-off, 'y': yt4-off}, {'x': xl3-off, 'y': yt4-off}, {'x': xl3-off, 'y': yb4+off}, {'x': xl2-off, 'y': yb4+off}, ] kicad_mod.append(PolygoneLine(polygone=tab, layer='F.SilkS', width=configuration['silk_line_width'])) ############################ Pin 1 ################################ # Pin 1 designator pin1_sl = 2.4 pin1 = [ {'x': body_edge['left'], 'y': -pin1_sl/2}, {'x': body_edge['left'] + pin1_sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': pin1_sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'], x_mirror=(body_edge['left']+body_edge['right'])/2)) x = -pad_size[0]/2 - pad_silk_off m = 0.4 pin = [ {'x': x,'y': 0}, {'x': x-2*m,'y': -m}, {'x': x-2*m,'y': +m}, {'x': x,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer='F.SilkS')) # pin1 = [ # {'x': 0, 'y': 8}, # {'x': 0.5, 'y': 9}, # {'x': -0.5, 'y': 9}, # {'x': 0, 'y': 8}, # ] # kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=0.12)) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for version in version_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, version_params[version], configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_mini-fit-sr_tht_top_dual.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Mini-Fit_Sr" series_long = 'Mini-Fit Sr. Power Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/439151404_sd.pdf' #pins_per_row per row pins_per_row_range = [3, 4, 5, 6, 7] #Molex part number #n = number of circuits per row part_code = "43915-xx{n:02}" pitch = 10 drill = 2.8 offset_second_pad = 4.4 pitch_row = offset_second_pad + 8.06 pad_to_pad_clearance = 3 max_annular_ring = 1 min_annular_ring = 0.15 #locating pins x_loc = 8.43 r_loc = 3.0 pad_size = [offset_second_pad + 0.1, pitch - pad_to_pad_clearance] if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring version_params = { 'with_thermals':{ 'description': ', With thermal vias in pads', 'fp_name_suffix': '_ThermalVias', 'thermals': True }, 'only_pads':{ 'description': '', 'fp_name_suffix': '', 'thermals': False } } def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = part_code.format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions #ref: http://www.molex.com/pdm_docs/sd/439151404_sd.pdf #A = distance between mounting holes A = pins * pitch + 1.41 #B = distance between end pin centers B = (pins - 1) * pitch #E = length of part E = pins * pitch + 0.9 #connector width W = 19.16 #corner positions y1 = -(E-B)/2 y2 = y1 + E x1 = -1.15 x2 = x1 + W TL = 5 TW = 13 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = { 'left': -pad_size[0]/2, 'right': pitch_row + offset_second_pad + pad_size[0]/2 } pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 #generate the pads for row_idx in range(2): for pad_idx in range(2): kicad_mod.append(PadArray( pincount=pins, start=[row_idx*pitch_row + pad_idx*offset_second_pad, 0], initial=row_idx*pins+1, y_spacing=pitch, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_THT, tht_pad1_shape=Pad.SHAPE_RECT)) #thermal vias d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for yi in range(pins): for xi in range(number_of_rows): n = xi*pins + yi + 1 pad_center_x = xi*pitch_row + offset_second_pad/2 pad_center_y = yi*pitch pad_l = offset_second_pad + pad_size[0] dy = (pad_size[1] - 2*thermal_to_pad_edge)/2 dx = (pad_l - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, x_spacing=dx*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y - dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y + dy], pincount=5, x_spacing=dx, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) # locating pins kicad_mod.append(Pad(at=[x_loc, 5], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=r_loc, drill=r_loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[x_loc, B/2-A/2], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=r_loc+0.5, drill=r_loc, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[x_loc, B/2+A/2], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=r_loc+0.5, drill=r_loc, layers=Pad.LAYERS_THT)) #mark pin-1 (bottom layer) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -pad_size[1]/2], end=[offset_second_pad + pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) #draw connector outline (basic) kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], width=configuration['fab_line_width'], layer='F.Fab')) #connector outline on F.SilkScreen off = configuration['silk_line_width'] corner = [ {'y': -pad_size[1]/2 - pad_silk_off, 'x': x1-off}, {'y': y1 - off, 'x': x1-off}, {'y': y1 - off, 'x': x_loc-r_loc/2-0.5}, ] # kicad_mod.append(PolygoneLine(polygone=corner, # width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(Line(start=[x_loc-r_loc/2-0.5, y1 - off], end=[x_loc-TW/2-off, y1 - off], width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=corner,y_mirror=B/2, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=corner,x_mirror=x_loc, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=corner,y_mirror=B/2,x_mirror=x_loc, width=configuration['silk_line_width'], layer='F.SilkS')) #silk-screen between each pad for i in range(pins-1): ya = i * pitch + pad_size[1]/2 + pad_silk_off yb = (i+1) * pitch - pad_size[1]/2 - pad_silk_off kicad_mod.append(Line(start=[x1-off, ya],end=[x1-off, yb], width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(Line(start=[x2+off, ya],end=[x2+off, yb], width=configuration['silk_line_width'], layer='F.SilkS')) #draw the tabs at each end def offsetPoly(poly_points, o , center_x, center_y): new_points = [] for point in poly_points: new_points.append( { 'y': point['y'] + (o if point['y'] > center_y else -o), 'x': point['x'] + (o if point['x'] > center_x else -o) } ) return new_points tab = [ {'y': y1,'x': x_loc-TW/2}, {'y': y1-TL,'x': x_loc-TW/2}, {'y': y1-TL,'x': x_loc+TW/2}, {'y': y1,'x': x_loc+TW/2}, ] kicad_mod.append(PolygoneLine(polygone=tab, width=configuration['fab_line_width'], layer='F.Fab')) kicad_mod.append(PolygoneLine(polygone=tab, y_mirror=B/2, width=configuration['fab_line_width'], layer='F.Fab')) tap_off = offsetPoly(tab, off, x_loc, B/2) kicad_mod.append(PolygoneLine(polygone=tap_off, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=tap_off, y_mirror=B/2, width=configuration['silk_line_width'], layer='F.SilkS')) bounding_box['top'] = y1 - TL bounding_box['bottom'] = y2 + TL #inner-tab T = 2 tab = [ {'y': y1-off,'x': x_loc-TW/2-off+T}, {'y': y1-off-TL+T,'x': x_loc-TW/2-off+T}, {'y': y1-off-TL+T,'x': x_loc+TW/2+off-T}, {'y': y1-off,'x': x_loc+TW/2+off-T}, ] kicad_mod.append(PolygoneLine(polygone=tab, width=configuration['silk_line_width'], layer='F.SilkS')) kicad_mod.append(PolygoneLine(polygone=tab,y_mirror=B/2, width=configuration['silk_line_width'], layer='F.SilkS')) #pin-1 marker x = x1 - 1.5 m = 0.4 pin = [ {'x': x,'y': 0}, {'x': x-2*m,'y': -m}, {'x': x-2*m,'y': +m}, {'x': x,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer='F.SilkS')) sl=3 pin = [ {'x': body_edge['left'], 'y': -sl/2}, {'x': body_edge['left'] + sl/sqrt(2), 'y': 0}, {'x': body_edge['left'], 'y': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for version in version_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, version_params[version], configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_mini-fit_Jr_tht_side_dual-row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "Mini-Fit_Jr" series_long = 'Mini-Fit Jr. Power Connectors' manufacturer = 'Molex' orientation = 'H' number_of_rows = 2 #pins_per_row_per_row per row pins_per_row_range = range(1,13) #Molex part number #n = number of circuits per row variant_params = { 'peg':{ 'mount_pins': 'plastic_peg', 'descriptive_name': 'Snap-in Plastic Peg PCB Lock', 'datasheet': 'http://www.molex.com/pdm_docs/sd/039300020_sd.pdf', 'part_code': {'mpn':"39-30-0{n:02d}0",'eng_num':"5569-{n:02}A2"}, }, 'flange':{ 'mount_pins': 'screw_flange', 'descriptive_name': 'PCB Mounting Flange', 'datasheet': 'http://www.molex.com/pdm_docs/sd/039291047_sd.pdf', 'part_code': {'mpn':"39-29-4{n:02d}9",'eng_num':"5569-{n:02}A1"}, } } pitch = 4.2 drill = 1.8 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 1.5 max_annular_ring = 0.95 min_annular_ring = 0.15 row = 5.5 pad_size = [pitch - pad_to_pad_clearance, row - pad_to_pad_clearance] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape = Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, variant, configuration): silk_pad_off = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 mpn = variant_params[variant]['part_code']['mpn'].format(n=pins_per_row*2) old_mpn = variant_params[variant]['part_code']['eng_num'].format(n=pins_per_row*2) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=old_mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, example for new mpn: {:s}, {:d} Pins per row, Mounting: {:s} ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format( series_long, old_mpn, mpn, pins_per_row, variant_params[variant]['descriptive_name'], variant_params[variant]['datasheet'])) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) tags += variant_params[variant]['mount_pins'] kicad_mod.setTags(tags) peg = variant_params[variant]['mount_pins'] == 'plastic_peg' #calculate fp dimensions #connector length A = pins_per_row * pitch + 1.2 #pin centers B = (pins_per_row - 1) * pitch #plasic pin-lock C = A + 4 #connector width W = 9.6 #corner positions x1 = -(A-B)/2 x2 = x1 + A y1 = -7.3 - 6.6 y2 = y1 + 12.8 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['bottom'] = row + pad_size[1]/2 #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins_per_row, initial=row_idx*pins_per_row+1, start=[0, row_idx*row], x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) off = configuration['silk_fab_offset'] #draw the 'peg' version #http://www.molex.com/pdm_docs/sd/026013127_sd.pdf #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) if peg: loc = 3.00 if pins_per_row > 2: # two mounting holes kicad_mod.append(Pad(at=[0,-7.3],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[0,-7.3],radius=loc/2+0.1)) kicad_mod.append(Pad(at=[B,-7.3],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[B,-7.3],radius=loc/2+0.1)) else: #single hole kicad_mod.append(Pad(at=[B/2,-7.3],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) #kicad_mod.append(Circle(center=[B/2,-7.3],radius=loc/2+0.1)) #draw the outline of the connector on the silkscreen poly = [ {'x': -2,'y': y2+off}, {'x': x1-off,'y': y2+off}, {'x': x1-off,'y': y1-off}, {'x': B/2,'y': y1-off}, ] kicad_mod.append(PolygoneLine(polygone=poly, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly, x_mirror=B/2, layer='F.SilkS', width=configuration['silk_line_width'])) #draw the 'screw' version #http://www.molex.com/pdm_docs/sd/039291027_sd.pdf else: loc = 3.2 kicad_mod.append(Pad(at=[-4.5, -4.2],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[B+4.5, -4.2],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc, drill=loc, layers=Pad.LAYERS_NPTH)) bounding_box['left'] = -15.4/2 bounding_box['right'] = B + 15.4/2 #draw the connector outline on silkscreen layer poly = [ {'x': x1,'y': y2-6.2}, {'x': -15.4/2,'y': y2-6.2}, {'x': -15.4/2,'y': y2}, {'x': x1,'y': y2} ] kicad_mod.append(PolygoneLine(polygone=poly, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly, x_mirror=B/2, layer='F.Fab', width=configuration['fab_line_width'])) poly = [ {'x': B/2,'y': y1-off}, {'x': x1-off,'y': y1-off}, {'x': x1-off,'y': y2-6.2-off}, {'x': -15.4/2 - off,'y': y2-6.2-off}, {'x': -15.4/2 - off,'y': y2+off}, {'x': -2,'y': y2+off}, ] kicad_mod.append(PolygoneLine(polygone=poly)) kicad_mod.append(PolygoneLine(polygone=poly, x_mirror=B/2, layer='F.SilkS', width=configuration['silk_line_width'])) #draw the pins_per_row on the Silkscreen layer o = pad_size[1]/2+silk_pad_off w = 0.3 for i in range(pins_per_row): x = i * pitch ya = o yb = row - o kicad_mod.append(Line(start=[x-w,ya],end=[x-w,yb], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x+w,ya],end=[x+w,yb], layer='F.SilkS', width=configuration['silk_line_width'])) #draw lines between each pin off = 0.1 for i in range(pins_per_row-1): xa = i * pitch + pad_size[0] / 2 + silk_pad_off xb = (i+1) * pitch - pad_size[0] / 2 - silk_pad_off kicad_mod.append(Line(start=[xa,y2+off],end=[xb,y2+off], layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 marker x = -2 m = 0.3 arrow = [ {'x': x,'y': 0}, {'x': x-2*m,'y': +m}, {'x': x-2*m,'y': -m}, {'x': x,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=arrow, layer='F.SilkS', width=configuration['silk_line_width'])) sl = 2 pin = [ {'x': -sl/2, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom']-sl/sqrt(2)}, {'x': sl/2, 'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) if peg: kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) else: cxb_left = roundToBase(body_edge['left'] - CrtYd_offset, CrtYd_grid) cxp_left = roundToBase(-pad_size[0]/2 - CrtYd_offset, CrtYd_grid) cyb_bottom = roundToBase(body_edge['bottom'] + CrtYd_offset, CrtYd_grid) cyb_mount_top = roundToBase(body_edge['bottom'] -6.2 - CrtYd_offset, CrtYd_grid) poly_crtyd = [ {'x': B/2, 'y': cy1}, {'x': cxb_left, 'y': cy1}, {'x': cxb_left, 'y': cyb_mount_top}, {'x': cx1, 'y': cyb_mount_top}, {'x': cx1, 'y': cyb_bottom}, {'x': cxp_left, 'y': cyb_bottom}, {'x': cxp_left, 'y': cy2}, {'x': B/2, 'y': cy2}, ] kicad_mod.append(PolygoneLine( polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(PolygoneLine( polygone=poly_crtyd, x_mirror=B/2 if B/2 != 0 else 0.000000001, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_mini-fit_Jr_tht_top_dual-row.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "Mini-Fit_Jr" series_long = 'Mini-Fit Jr. Power Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 #pins_per_row_per_row per row pins_per_row_range = range(1,13) #Molex part number #n = number of circuits per row variant_params = { 'peg':{ 'mount_pins': 'plastic_peg', 'descriptive_name': 'Snap-in Plastic Peg PCB Lock', 'datasheet': 'http://www.molex.com/pdm_docs/sd/039289068_sd.pdf', 'part_code': {'mpn':"39-28-9{n:02d}x",'eng_num':"5566-{n:02}A2"}, }, 'no-peg':{ 'mount_pins': '', 'descriptive_name': '', 'datasheet': 'http://www.molex.com/pdm_docs/sd/039281043_sd.pdf', 'part_code': {'mpn':"39-28-x{n:02d}x",'eng_num':"5566-{n:02}A"}, } } pitch = 4.2 drill = 1.4 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 1.5 max_annular_ring = 0.95 min_annular_ring = 0.15 row = 5.5 pad_size = [pitch - pad_to_pad_clearance, row - pad_to_pad_clearance] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape = Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE def generate_one_footprint(pins_per_row, variant, configuration): peg = variant_params[variant]['mount_pins'] == 'plastic_peg' silk_pad_off = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 mpn = variant_params[variant]['part_code']['mpn'].format(n=pins_per_row*2) old_mpn = variant_params[variant]['part_code']['eng_num'].format(n=pins_per_row*2) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=old_mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, example for new mpn: {:s}, {:d} Pins per row, Mounting: {:s} ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format( series_long, old_mpn, mpn, pins_per_row, variant_params[variant]['descriptive_name'], variant_params[variant]['datasheet'])) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation]) tags += variant_params[variant]['mount_pins'] kicad_mod.setTags(tags) #calculate fp dimensions #connector length A = pins_per_row * pitch + 1.2 #pin centers B = (pins_per_row - 1) * pitch #plasic pin-lock C = A + 4 #connector width W = 9.6 #corner positions x1 = -(A-B)/2 x2 = x1 + A y2 = row + 1.85 y1 = y2 - W #tab length tab_l = 3.4 #tab width tab_w = 1.4 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['bottom'] = body_edge['bottom'] + tab_w off = configuration['silk_fab_offset'] #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(2): kicad_mod.append(PadArray( pincount=pins_per_row, initial=row_idx*pins_per_row+1, start=[0, row_idx*row], x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #add PCB locators if needed pad_silk_offset = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 if peg: loc = 3.00 mounting_pin_y = row - 0.46 lx1 = B/2-C/2 lx2 = B/2+C/2 kicad_mod.append(Pad(at=[lx1, mounting_pin_y],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[lx2, mounting_pin_y],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=loc,drill=loc, layers=Pad.LAYERS_NPTH)) bounding_box['left'] = lx1-loc/2 bounding_box['right'] = lx2+loc/2 ######################## Fab ############################ mount_pin_radius = loc/2 kicad_mod.append(Arc(center=[lx1,mounting_pin_y], start=[lx1,mounting_pin_y+mount_pin_radius], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y-mount_pin_radius], end=[x1,mounting_pin_y-mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y+mount_pin_radius], end=[x1,mounting_pin_y+mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Arc(center=[lx2,mounting_pin_y], start=[lx2,mounting_pin_y-mount_pin_radius], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y-mount_pin_radius], end=[x2,mounting_pin_y-mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y+mount_pin_radius], end=[x2,mounting_pin_y+mount_pin_radius], layer='F.Fab', width=configuration['fab_line_width'])) ######################## Silk ############################ mount_pin_radius = loc/2 + silk_pad_off kicad_mod.append(Arc(center=[lx1,mounting_pin_y], start=[lx1,mounting_pin_y+mount_pin_radius], angle=180, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y-mount_pin_radius], end=[x1-off,mounting_pin_y-mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx1,mounting_pin_y+mount_pin_radius], end=[x1-off,mounting_pin_y+mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Arc(center=[lx2,mounting_pin_y], start=[lx2,mounting_pin_y-mount_pin_radius], angle=180, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y-mount_pin_radius], end=[x2+off,mounting_pin_y-mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[lx2,mounting_pin_y+mount_pin_radius], end=[x2+off,mounting_pin_y+mount_pin_radius], layer='F.SilkS', width=configuration['silk_line_width'])) #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab',width=configuration['fab_line_width'])) #draw the outline of the tab kicad_mod.append(PolygoneLine(polygone=[ {'x': B/2 - tab_l/2,'y': y2}, {'x': B/2 - tab_l/2,'y': y2 + tab_w}, {'x': B/2 + tab_l/2,'y': y2 + tab_w}, {'x': B/2 + tab_l/2,'y': y2}, ], layer='F.Fab', width=configuration['fab_line_width'])) #draw the outline of each pin slot (alternating shapes) #slot size S = 3.3 def square_slot(x,y): kicad_mod.append(RectLine(start=[x-S/2,y-S/2], end=[x+S/2,y+S/2], layer='F.Fab', width=configuration['fab_line_width'])) def notch_slot(x,y): kicad_mod.append(PolygoneLine(polygone=[ {'x': x-S/2, 'y': y+S/2}, {'x': x-S/2, 'y': y-S/4}, {'x': x-S/4, 'y': y-S/2}, {'x': x+S/4, 'y': y-S/2}, {'x': x+S/2, 'y': y-S/4}, {'x': x+S/2, 'y': y+S/2}, {'x': x-S/2, 'y': y+S/2}, ], layer='F.Fab', width=configuration['fab_line_width'])) q = 1 notch = True for i in range(pins_per_row): if notch: y_square = row/2 - 4.2/2 y_notch = row/2 + 4.2/2 else: y_square = row/2 + 4.2/2 y_notch = row/2 - 4.2/2 square_slot(i * pitch, y_square) notch_slot(i*pitch, y_notch) q -= 1 if (q == 0): q = 2 notch = not notch #draw the outline of the connector on the silkscreen outline = [ {'x': B/2,'y': y1-off}, {'x': x1-off,'y': y1-off}, {'x': x1-off,'y': y2+off}, {'x': B/2 - tab_l/2 - off,'y': y2+off}, {'x': B/2 - tab_l/2 - off,'y': y2 + off + tab_w}, {'x': B/2, 'y': y2 + off + tab_w}, ] kicad_mod.append(PolygoneLine(polygone=outline, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline, x_mirror=B/2, layer="F.SilkS", width=configuration['silk_line_width'])) #pin-1 marker L = 2.5 O = 0.35 pin = [ {'x': x1 + L,'y': y1 - O}, {'x': x1 - O,'y': y1 - O}, {'x': x1 - O,'y': y1 + L}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) if peg: cx3 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx4 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) mount_pin_radius = loc/2 cy3=roundToBase(mounting_pin_y - mount_pin_radius - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) poly_crtyd = [ {'x': cx3, 'y': cy1}, {'x': cx3, 'y': cy3}, {'x': cx1, 'y': cy3}, {'x': cx1, 'y': cy2}, {'x': cx2, 'y': cy2}, {'x': cx2, 'y': cy3}, {'x': cx4, 'y': cy3}, {'x': cx4, 'y': cy1}, {'x': cx3, 'y': cy1} ] kicad_mod.append(PolygoneLine(polygone=poly_crtyd, layer='F.CrtYd', width=configuration['courtyard_line_width'])) else: kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_nano-fit_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Nano-Fit" series_long = 'Nano-Fit Power Connectors' manufacturer = 'Molex' orientation = 'H' #pins_per_row per row pins_per_row_range = range(2,9) #Molex part number #n = number of circuits per row pitch = 2.5 drill = 1.2 pitch_row = 2.5 pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 min_annular_ring = 0.15 version_params = { 'dual':{ 'number_of_rows': 2, 'datasheet': 'http://www.molex.com/pdm_docs/sd/1053141208_sd.pdf', 'mpn': "105314-xx{n:02}" }, 'single':{ 'number_of_rows': 1, 'datasheet': 'http://www.molex.com/pdm_docs/sd/1053131208_sd.pdf', 'mpn': "105313-xx{n:02}" } } def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = params['mpn'].format(n=pins*params['number_of_rows']) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=params['number_of_rows'], pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, pins, params['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if params['number_of_rows'] == 2: pad_size = [pitch_row - pad_to_pad_clearance, pitch - pad_to_pad_clearance] else: pad_size = [drill + 2*max_annular_ring, pitch - pad_to_pad_clearance] if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape=Pad.SHAPE_CIRCLE #A = connector length A = pins * pitch + 0.94 #B = pin center distance B = (pins - 1) * pitch #W = thickness of plastic base W = 8.46 #locating pin position C = B #corner positions for plastic housing outline y1 = -(A-B)/2 y2 = y1 + A x2 = (params['number_of_rows'] - 1) * pitch_row + 10.38 x1 = x2 - W off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['left'] = -pad_size[0]/2 pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for r in range(params['number_of_rows']): kicad_mod.append(PadArray( pincount=pins, initial=r*pins+1, start=[r*pitch_row,0], y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #add the locating pins y_loc_a = B/2 - C/2 y_loc_b = B/2 + C/2 x_loc = (params['number_of_rows']-1)*pitch_row+7.18 r_loc = 1.7 kicad_mod.append(Pad(at=[x_loc,y_loc_a],size=r_loc,drill=r_loc,type=Pad.TYPE_NPTH,shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[x_loc,y_loc_b],size=r_loc,drill=r_loc,type=Pad.TYPE_NPTH,shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) #add outline to F.Fab kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],offset=off, width=configuration['silk_line_width'], layer="F.SilkS")) #draw the pins for i in range(pins): y = i * pitch x = (params['number_of_rows'] - 1) * pitch_row + pad_size[0]/2 + pad_silk_off w = 0.15 kicad_mod.append(RectLine(start=[x1-off,y+w],end=[x,y-w], width=configuration['silk_line_width'], layer="F.SilkS")) #pin-1 marker y = - pad_size[1]/2- pad_silk_off m = 0.3 pin = [ {'x': 0,'y': y}, {'x': m,'y': y-m*sqrt(2)}, {'x': -m,'y': y-m*sqrt(2)}, {'x': 0,'y': y}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for version in version_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, version_params[version], configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_nano-fit_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Nano-Fit" series_long = 'Nano-Fit Power Connectors' manufacturer = 'Molex' orientation = 'V' #pins_per_row per row pins_per_row_range = range(2,9) #Molex part number #n = number of circuits per row pitch = 2.5 drill = 1.2 pitch_row = 2.5 pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 min_annular_ring = 0.15 version_params = { 'dual':{ 'number_of_rows': 2, 'datasheet': "http://www.molex.com/pdm_docs/sd/1053101208_sd.pdf", 'mpn': "105310-xx{n:02}" }, 'single':{ 'number_of_rows': 1, 'datasheet': 'http://www.molex.com/pdm_docs/sd/1053091203_sd.pdf', 'mpn': "105309-xx{n:02}" } } def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = params['mpn'].format(n=pins*params['number_of_rows']) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=params['number_of_rows'], pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, pins, params['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if params['number_of_rows'] == 2: pad_size = [pitch_row - pad_to_pad_clearance, pitch - pad_to_pad_clearance] else: pad_size = [drill + 2*max_annular_ring, pitch - pad_to_pad_clearance] if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape=Pad.SHAPE_CIRCLE #A = connector length A = pins * pitch + 0.94 #B = pin center distance B = (pins - 1) * pitch #W = thickness of plastic base W = params['number_of_rows'] * pitch_row + 0.98 #locating pin position if pins in [3,5,7]: C = B/2 - 1.25 else: C = B/2 #corner positions for plastic housing outline y1 = -(A-B)/2 y2 = y1 + A x2 = (params['number_of_rows'] - 1)* pitch_row+1.74 x1 = x2 - W TL = 5.2 TW = 2.86 off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['left'] = body_edge['left']-TW pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 #generate the pads if pins <= 3: if configuration['kicad4_compatible']: kicad_mod.append(Pad(number=1, at=[0, 0], size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number=1, at=[0, -pad_size[1]/4], size=[pad_size[0],pad_size[1]/2], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=['F.Cu', 'F.Mask'])) kicad_mod.append(Pad(number=1, at=[0, -pad_size[1]/4], size=[pad_size[0],pad_size[1]/2], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=['B.Cu', 'B.Mask'])) else: kicad_mod.append(ChamferedPad(number=1, at=[0, 0], size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, chamfer_size=0.4, radius_ratio=0.25, maximum_radius=0.25, corner_selection=CornerSelection({CornerSelection.BOTTOM_LEFT:True}))) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for r in range(params['number_of_rows']): pincount = pins initial = r*pins+1 start=[r*pitch_row, 0] if r == 0 and pins <= 3: pincount = pins -1 initial = 2 start=[0, pitch] kicad_mod.append(PadArray( pincount=pincount, initial=initial, start=start, y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #add the locating pin kicad_mod.append(Pad(at=[-1.34, C], size=1.3, drill=1.3, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_NPTH)) #add outline to F.Fab #kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],layer='F.Fab')) #and to the silkscreen #and draw the tab def outline(off = 0, grid = 0): out = [ {'y': roundToBase(B/2, grid), 'x': roundToBase(x2+off, grid)}, {'y': roundToBase(y1-off, grid), 'x': roundToBase(x2+off, grid)}, {'y': roundToBase(y1-off, grid), 'x': roundToBase(x1-off, grid)}, {'y': roundToBase(B/2-TL/2-off, grid), 'x': roundToBase(x1-off, grid)}, {'y': roundToBase(B/2-TL/2-off, grid), 'x': roundToBase(x1-TW-off, grid)}, {'y': roundToBase(B/2, grid), 'x': roundToBase(x1-TW-off, grid)} ] return out kicad_mod.append(PolygoneLine(polygone=outline(), layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(), layer='F.Fab', width=configuration['fab_line_width'], y_mirror=B/2)) kicad_mod.append(PolygoneLine(polygone=outline(off = off), layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(off = off), layer='F.SilkS', width=configuration['silk_line_width'], y_mirror=B/2)) CrtYd_off = configuration['courtyard_offset']['connector'] kicad_mod.append(PolygoneLine( polygone=outline(off = CrtYd_off, grid=configuration['courtyard_grid']), layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(PolygoneLine( polygone=outline(off = CrtYd_off, grid=configuration['courtyard_grid']), layer='F.CrtYd', width=configuration['courtyard_line_width'], y_mirror=B/2)) # draw the tab kicad_mod.append(RectLine(start=[x1+2*off, B/2-TL/2],end=[x1-TW, B/2+TL/2], offset=-0.5, width=configuration['fab_line_width'], layer='F.Fab')) #draw the pins! # o = 0.475 * pitch # for i in range(pins): # for j in range(params['number_of_rows']): # y = i * pitch # x = j * pitch # # kicad_mod.append(RectLine(start=[x-o,y-o],end=[x+o,y+o], layer='F.Fab', width=configuration['fab_line_width'])) #pin-1 marker p1m_off = configuration['silk_fab_offset'] + 0.3 p1m_b = B/2-TL/2 - off if p1m_b > 0: p1m_b = 0 pin = [ {'x': 0,'y': body_edge['top'] - p1m_off}, {'x': body_edge['left'] - p1m_off,'y': body_edge['top'] - p1m_off}, {'x': body_edge['left'] - p1m_off,'y': p1m_b} ] kicad_mod.append(PolygoneLine(polygone=pin, layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['top'], 'x': -sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': 0}, {'y': body_edge['top'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':bounding_box['top'] - CrtYd_off, 'bottom':bounding_box['bottom'] + CrtYd_off}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for version in version_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, version_params[version], configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_picoblade_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PicoBlade" series_long = 'PicoBlade Connector System' manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/530480210_sd.pdf' #pins_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row part_code = "53048-{n:02}10" pitch = 1.25 drill = 0.5 pad_to_pad_clearance = 0.8 max_annular_ring = 0.4 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions B = (pins - 1) * pitch C = B + 1.8 A = B + 3 #connector width W = 5.5 #corner positions x1 = (B-A) / 2 x2 = x1 + A y1 = -1.05 y2 = y1 + W # distance from pins in y dir P = 0.75 # thickness of end bosses T = 0.85 off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': -P } bounding_box = body_edge.copy() # generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[0,0], pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #pin-1 marker o = 0.4 pin1 = [ {'x': x1 + T + o,'y': -P - o}, {'x': x1 + T + o,'y': y1 - o}, {'x': x1 + T + o - 0.5,'y': y1 - o}, ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['top'], 'x': -sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': 0}, {'y': body_edge['top'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) #component outline (configurable offset) def outline(off = 0, grid = 0): out = [ {'x': roundToBase(B/2, grid), 'y': roundToBase(-P - off, grid)}, {'x': roundToBase(x1 + T + off, grid), 'y': roundToBase(-P - off, grid)}, {'x': roundToBase(x1 + T + off, grid), 'y': roundToBase(y1 - off, grid)}, {'x': roundToBase(x1 - off, grid), 'y': roundToBase(y1 - off, grid)}, {'x': roundToBase(x1 - off, grid), 'y': roundToBase(y2 + off, grid)}, {'x': roundToBase(B/2, grid), 'y': roundToBase(y2 + off, grid)}, ] return out #courtyard CrtYd_off = configuration['courtyard_offset']['connector'] grid = configuration['courtyard_grid'] kicad_mod.append(PolygoneLine(polygone=outline(off=CrtYd_off, grid=grid), layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(off=CrtYd_off, grid=grid), layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=B/2)) #outline F.Fab kicad_mod.append(PolygoneLine(polygone=outline(), layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(), layer='F.Fab', width=configuration['fab_line_width'], x_mirror=B/2)) #outline F.SilkS kicad_mod.append(PolygoneLine(polygone=outline(off=off), layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=outline(off=off), x_mirror=B/2, layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':bounding_box['top']-CrtYd_off, 'bottom':bounding_box['bottom']+CrtYd_off}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_picoblade_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "PicoBlade" series_long = 'PicoBlade Connector System' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.molex.com/pdm_docs/sd/530470610_sd.pdf' #pins_per_row per row pins_per_row_range = range(2,16) #Molex part number #n = number of circuits per row part_code = "53047-{n:02}10" pitch = 1.25 drill = 0.5 pad_to_pad_clearance = 0.8 max_annular_ring = 0.4 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins - 1) * pitch B = A + 1.8 C = A + 3 #connector width W = 3.2 #side thickness T = 0.4 #corner positions x1 = (A - C) / 2 x2 = x1 + C y2 = 1.15 y1 = y2 - W off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() # generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[0,0], pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) # outline on Fab kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab', width=configuration['fab_line_width'])) # outline on SilkScreen kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2],offset=off, layer='F.SilkS', width=configuration['silk_line_width'])) inline = [ {'x': A/2,'y': y2 - T}, {'x': x1 + T,'y': y2 - T}, {'x': x1 + T,'y': 0}, {'x': x1 + T/2,'y': 0}, {'x': x1 + T/2,'y': -2*T}, {'x': x1 + T,'y': -2*T}, {'x': x1 + T,'y': y1 + T}, {'x': A/2,'y': y1 + T}, ] kicad_mod.append(PolygoneLine(polygone=inline, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=inline, x_mirror=A/2, layer='F.SilkS', width=configuration['silk_line_width'])) #pin-1 mark L = 1 kicad_mod.append(Line(start=[x1-0.4,y2+0.4], end=[x1-0.4,y2+0.4-L], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[x1-0.4,y2+0.4], end=[x1-0.4+L,y2+0.4], layer='F.SilkS', width=configuration['silk_line_width'])) sl=1 pin = [ {'y': body_edge['bottom'], 'x': -sl/2}, {'y': body_edge['bottom'] - sl/sqrt(2), 'x': 0}, {'y': body_edge['bottom'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_picoflex_smd_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Picoflex" series_long = 'Picoflex Ribbon-Cable Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/908140004_sd.pdf' #pins_per_row per row pins_range = (4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26) #Molex part number #n = number of circuits per row part_code = "90814-00{n:02}" pitch = 1.27 pitch_row = 2.54 def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) CrtYd_off = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] body_edge = {} bounding_box = {} # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # # Draw all graphical objects # BodyWidth = 4.1 BodyHeight = ((pins - 1) * pitch) + (2 * 2.525) # HalfBodyWidth = BodyWidth / 2 HalfBodyHeight = BodyHeight / 2 PadWidth = 2 PadHeight = 1.2 # AllPadsWidth = 6 AllPadsHeight = ((pins - 1) * pitch) # HalfAllPadsWidth = AllPadsWidth / 2 HalfAllPadsHeight = AllPadsHeight / 2 GuideHoleDrillSize = 1.9 GuideHoleX1 = 1.1 - HalfAllPadsWidth GuideHoleY1 = -1.925 - HalfAllPadsHeight GuideHoleX1 = 1.1 - HalfAllPadsWidth GuideHoleY2 = 1.925 + HalfAllPadsHeight KeepOutAreaWidth = 7.9 KeepOutAreaHeight = BodyHeight body_edge['right'] = HalfBodyWidth body_edge['left'] = -HalfBodyWidth body_edge['top'] = -HalfBodyHeight body_edge['bottom'] = HalfBodyHeight bounding_box['right'] = HalfAllPadsWidth + PadWidth/2 bounding_box['left'] = -bounding_box['right'] bounding_box['bottom'] = GuideHoleY2 + GuideHoleDrillSize/2 + 0.175 bounding_box['top'] = -bounding_box['bottom'] # # Generate the pads # tpc = int(pins / 2) kicad_mod.append(PadArray( start=[round(0 - HalfAllPadsWidth, 2), round(0 - HalfAllPadsHeight, 2)], pincount=tpc, initial=1, increment=2, x_spacing=0, y_spacing=2*pitch, size=[PadWidth, PadHeight], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray( start=[round(HalfAllPadsWidth, 2), round(pitch - HalfAllPadsHeight, 2)], pincount=tpc, initial=2, increment=2, x_spacing=0, y_spacing=2*pitch, size=[PadWidth, PadHeight], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) # # Generate the drill holes # kicad_mod.append(Pad(at=[GuideHoleX1, GuideHoleY1],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=GuideHoleDrillSize, drill=GuideHoleDrillSize, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[GuideHoleX1, GuideHoleY2],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=GuideHoleDrillSize, drill=GuideHoleDrillSize, layers=Pad.LAYERS_NPTH)) # # Add the Fab line # # Start in upper right corner x1 = HalfBodyWidth y1 = 0 - HalfBodyHeight x2 = x1 y2 = y1 + BodyHeight kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.Fab', width=configuration['fab_line_width'])) # # Bottom line to bottom drill hole x1 = x2 y1 = y2 x2 = GuideHoleX1 + (GuideHoleDrillSize / 2) y2 = y2 kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.Fab', width=configuration['fab_line_width'])) # Arc around bottom drill hole ccx = GuideHoleX1 ccy = GuideHoleY2 csx = x2 csy = HalfAllPadsHeight + 2.525 kicad_mod.append(Arc( center=[round(ccx, 2), round(ccy, 2)], start=[round(csx, 2), round(csy, 2)], angle=230.0, layer='F.Fab', width=configuration['fab_line_width'])) # Left line from bottom drill hole to top drill hole including the Fab Pin 1 marker x1 = -HalfBodyWidth y1 = GuideHoleY2 - (GuideHoleDrillSize / 2) - 0.17 x2 = x1 y2 = 0 - (HalfAllPadsHeight - (PadHeight / 2)) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.Fab', width=configuration['fab_line_width'])) x1 = x2 y1 = y2 x2 = x1 + (PadHeight / 2) y2 = y2 - (PadHeight / 2) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.Fab', width=configuration['fab_line_width'])) x1 = x2 y1 = y2 x2 = x1 - (PadHeight / 2) y2 = y2 - (PadHeight / 2) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.Fab', width=configuration['fab_line_width'])) x1 = x2 y1 = y2 x2 = x1 y2 = GuideHoleY1 + (GuideHoleDrillSize / 2) + 0.17 kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.Fab', width=configuration['fab_line_width'])) # Arc around top drill hole ccx = GuideHoleX1 ccy = GuideHoleY1 csx = x1 csy = y2 kicad_mod.append(Arc( center=[round(ccx, 2), round(ccy, 2)], start=[round(csx, 2), round(csy, 2)], angle=230.0, layer='F.Fab', width=configuration['fab_line_width'])) # Top line to top drill hole x1 = HalfBodyWidth y1 = 0 - HalfBodyHeight x2 = GuideHoleX1 + (GuideHoleDrillSize / 2) + 0.02 y2 = y1 kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.Fab', width=configuration['fab_line_width'])) # # Add the Silk line # # Start in upper right corner x1 = HalfBodyWidth + 0.13 y1 = 0 - HalfBodyHeight - 0.13 x2 = x1 y2 = 0 - ((HalfAllPadsHeight - pitch) + (PadHeight / 2) + 0.3) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) y1 = 0 - ((HalfAllPadsHeight - pitch) - (PadHeight / 2) - 0.4) y2 = 0 - ((HalfAllPadsHeight - (3 *pitch)) + (PadHeight / 2) + 0.4) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) if (pins > 3): for halfpins in range(int((pins / 2)) - 2): y1 = y1 + (2 * pitch) y2 = y2 + (2 * pitch) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1 + 0.06, 2)], [round(x2, 2), round(y2 - 0.06, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) x1 = x1 y1 = HalfAllPadsHeight + (PadHeight / 2) + 0.3 x2 = HalfBodyWidth + 0.13 y2 = HalfBodyHeight + 0.13 kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) # # Bottom line to bottom drill hole x1 = x2 y1 = y2 x2 = GuideHoleX1 + (GuideHoleDrillSize / 2) + 0.1 y2 = y2 kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) # Arc around bottom drill hole ccx = GuideHoleX1 ccy = GuideHoleY2 csx = x2 csy = y2 kicad_mod.append(Arc( center=[round(ccx, 2), round(ccy, 2)], start=[round(csx, 2), round(csy, 2)], angle=222.8, layer='F.SilkS', width=configuration['silk_line_width'])) # Left line from bottom drill hole to top drill hole x1 = -HalfBodyWidth - 0.13 y1 = GuideHoleY2 - (GuideHoleDrillSize / 2) - 0.3 x2 = x1 y2 = y1 - 0.5 y2 = HalfAllPadsHeight - pitch + (PadHeight / 2) + 0.3 kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) y1 = ((HalfAllPadsHeight - pitch) - (PadHeight / 2) - 0.4) y2 = ((HalfAllPadsHeight - (3 *pitch)) + (PadHeight / 2) + 0.4) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) # Add small lines between pads if (pins > 3): for halfpins in range(int((pins / 2)) - 2): y1 = y1 - (2 * pitch) y2 = y2 - (2 * pitch) kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1 + 0.06, 2)], [round(x2, 2), round(y2 - 0.06, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) # Arc around top drill hole y2 = GuideHoleY1 + (GuideHoleDrillSize / 2) + 0.3 ccx = GuideHoleX1 ccy = GuideHoleY1 csx = x1 - 0.63 csy = y2 -0.35 # # xxx, yyy is the new pin 1 marker # xxx1 = csx yyy1 = csy xxx2 = xxx1 yyy2 = 0 - (HalfAllPadsHeight + (PadHeight / 2) + 0.3) kicad_mod.append(PolygoneLine( polygone=[[round(xxx1, 2), round(yyy1, 2)], [round(xxx2, 2), round(yyy2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) xxx1 = xxx2 yyy1 = yyy2 xxx2 = 0 - (HalfAllPadsWidth + (PadWidth / 2)) yyy2 = yyy1 kicad_mod.append(PolygoneLine( polygone=[[round(xxx1, 2), round(yyy1, 2)], [round(xxx2, 2), round(yyy2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) # kicad_mod.append(Arc( center=[round(ccx, 2), round(ccy, 2)], start=[round(csx, 2), round(csy, 2)], angle=191.0, layer='F.SilkS', width=configuration['silk_line_width'])) # Top line to top drill hole x1 = HalfBodyWidth + 0.13 y1 = 0 - HalfBodyHeight - 0.13 x2 = GuideHoleX1 + (GuideHoleDrillSize / 2) + 0.13 y2 = y1 kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) # # Add the pin 1 marker # # Start in upper right corner # x1 = 0 - (HalfAllPadsWidth + (PadWidth / 2) + 0.25 + 0.25) # y1 = 0 - HalfAllPadsHeight - 1 # x2 = x1 # y2 = round(y1 + 3, 0) # kicad_mod.append(PolygoneLine(polygone=[[round(x1, 2), round(y1, 2)], [round(x2, 2), round(y2, 2)]], layer='F.SilkS', width=configuration['silk_line_width'])) # # Add the keep out area # x1 = 0 - (KeepOutAreaWidth / 2) y1 = 0 - (KeepOutAreaHeight / 2) x2 = x1 + KeepOutAreaWidth y2 = y1 + KeepOutAreaHeight kicad_mod.append(RectLine(start=[round(x1, 2), round(y1, 2)], end=[round(x2, 2), round(y2, 2)], layer='Dwgs.User', width=0.1)) kicad_mod.append(Text(type='user', text='KEEPOUT', at=[0,0], rotation=90, layer='Cmts.User')) x1 = 0 - (KeepOutAreaWidth / 2) y1 = 0 - (KeepOutAreaHeight / 2) x2 = 0 - (KeepOutAreaWidth / 2) y2 = 0 - (KeepOutAreaHeight / 2) GridDelta = 2 * pitch dx1 = 0 dy1 = GridDelta yy1 = y1; while (x1 < (KeepOutAreaWidth / 2)): y1 = y1 + GridDelta yy1 = yy1 + dy1 if (y1 > ((KeepOutAreaHeight / 2))): yy1 = (KeepOutAreaHeight / 2) dy1 = 0 dx1 = y1 - (KeepOutAreaHeight / 2) x1 = (0 - (KeepOutAreaWidth / 2)) + dx1 x2 = x2 + GridDelta if (x2 >= ((KeepOutAreaWidth / 2))): x2 = (KeepOutAreaWidth / 2) y2 = y1 - KeepOutAreaWidth if (x1 < (KeepOutAreaWidth / 2)): kicad_mod.append(PolygoneLine( polygone=[[round(x1, 2), round(yy1, 2)], [round(x2, 2), round(y2, 2)]], layer='Dwgs.User',width=0.1)) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='left') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pins in pins_range: generate_one_footprint(pins, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_picoflex_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Picoflex" series_long = 'Picoflex Ribbon-Cable Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/903250004_sd.pdf' #pins_per_row per row pins_range = (4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26) #Molex part number #n = number of circuits per row part_code = "90325-00{n:02}" pitch = 1.27 pitch_row = 2.54 drill = 0.8 pad_to_pad_clearance = 0.8 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [drill + 0.5*2, drill + 0.25*2] pad_shape = Pad.SHAPE_OVAL def generate_one_footprint(pins, configuration): mpn = part_code.format(n=pins) CrtYd_off = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] body_edge = {} bounding_box = {} # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) GuideHoleDrillSize = 1.5 GuideHoleX1 = -1.48 GuideHoleY1 = -1.8 GuideHoleY2 = (pins - 1) * pitch - GuideHoleY1 StartFX = GuideHoleX1 StartFY = 0 - 2.755 # generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT tpc = int(pins / 2) for row_idx in range(2): kicad_mod.append(PadArray( start=[2*row_idx*pitch, row_idx*pitch], pincount=tpc, initial=row_idx+1, increment=2, x_spacing=0, y_spacing=2*pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) # Generate the drill holes stx = (pins - 1) * pitch + 1.8 kicad_mod.append(Pad(at=[GuideHoleX1, GuideHoleY1],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=GuideHoleDrillSize, drill=GuideHoleDrillSize, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(at=[GuideHoleX1, GuideHoleY2],type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=GuideHoleDrillSize, drill=GuideHoleDrillSize, layers=Pad.LAYERS_NPTH)) # # Top lines # x1 = StartFX y1 = StartFY x2 = x1 + 5 y2 = y1 kicad_mod.append(PolygoneLine( polygone=[[x1, y1], [x2, y2]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine( polygone=[[x1, y1 - 0.13], [x2 + 0.13, y2 - 0.13]], layer='F.SilkS', width=configuration['silk_line_width'])) body_edge['top'] = y1 bounding_box['top'] = y1 # # Right lines # x1 = x2 y1 = y2 x2 = x2 y2 = ((pins - 1) * pitch) + 2.755 kicad_mod.append(PolygoneLine( polygone=[[x1, y1], [x2, y2]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine( polygone=[[x1 + 0.13, y1 - 0.13], [x2 + 0.13, y2 + 0.13]], layer='F.SilkS', width=configuration['silk_line_width'])) body_edge['right'] = x1 bounding_box['right'] = x1 # # Bottom lines # x1 = x2 y1 = y2 x2 = StartFX y2 = y2 kicad_mod.append(PolygoneLine( polygone=[[x1, y1], [x2, y2]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine( polygone=[[x1 + 0.13, y1 + 0.13], [x2, y2 + 0.13]], layer='F.SilkS', width=configuration['silk_line_width'])) body_edge['bottom'] = y1 bounding_box['bottom'] = y1 # # Upper arcs # ccx = GuideHoleX1 ccy = GuideHoleY1 csx = GuideHoleX1 csy = -0.85 kicad_mod.append(Arc(center=[ccx, ccy], start=[csx, csy], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) ccx = GuideHoleX1 ccy = GuideHoleY1 csx = -1.61 csy = -0.72 kicad_mod.append(Arc(center=[ccx, ccy], start=[csx, csy], angle=180, layer='F.SilkS', width=configuration['silk_line_width'])) # # Left lines # x1 = GuideHoleX1 y1 = GuideHoleY1 + (GuideHoleY1 - StartFY) x2 = GuideHoleX1 y2 = GuideHoleY2 - (GuideHoleY1 - StartFY) x3 = 2 y3 = -0.5 kicad_mod.append(PolygoneLine(polygone=[[x1,y1], [x2, -0.5]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[[x2, -0.5], [x2 + 0.5, 0]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[[x2 + 0.5, 0], [x2, 0.5]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=[[x2, 0.5], [x2, y2]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine( polygone=[[x1 - 0.13, y1 + 0.13], [x2 - 0.13, y2 - 0.13]], layer='F.SilkS', width=configuration['silk_line_width'])) body_edge['left'] = x1 # # Bottom arcs # ccx = GuideHoleX1 ccy = GuideHoleY2 csx = GuideHoleX1 csy = ((pins - 1) * pitch) + 2.755 radius = abs(csy - ccy) kicad_mod.append(Arc(center=[ccx, ccy], start=[csx, csy], angle=180, layer='F.Fab', width=configuration['fab_line_width'])) bounding_box['left'] = ccx - radius ccx = GuideHoleX1 ccy = GuideHoleY2 csx = -1.47 csy = ((pins - 1) * pitch) + 2.755 + 0.13 kicad_mod.append(Arc(center=[ccx, ccy], start=[csx, csy], angle=170, layer='F.SilkS', width=configuration['silk_line_width'])) # pin 1 x = body_edge['left'] - 0.3 m = 0.3 pin = [ {'x': x,'y': 0}, {'x': x-2*m,'y': -m}, {'x': x-2*m,'y': +m}, {'x': x,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['silk_line_width'], layer='F.SilkS')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins in pins_range: generate_one_footprint(pins, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_sabre_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Sabre" series_long = 'Sabre Power Connector' manufacturer = 'Molex' orientation = 'H' number_of_rows = 1 #pins_per_row per row pins_per_row_range = [2, 3, 4, 5, 6] #Molex part number #n = number of circuits per row pitch = 7.49 drill = 1.78 offset_second_pad = 3.18 pad_to_pad_clearance = 3 max_annular_ring = 1 min_annular_ring = 0.15 #locating pins ret_dy = 13.13 ret_dx = 4.75 ret_drill = 3.00 ret_size = 4.00 pad_size = [pitch - pad_to_pad_clearance, offset_second_pad + 0.25] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring version_params = { 'with_thermals_lock':{ 'mpn': '43160-11{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/431605304_sd.pdf', 'description': ', With thermal vias in pads', 'fp_name_suffix': '_ThermalVias', 'thermals': True, 'lock': True }, 'only_pads_lock':{ 'mpn': '43160-11{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/431605304_sd.pdf', 'description': '', 'fp_name_suffix': '', 'thermals': False, 'lock': True }, 'with_thermals':{ 'mpn': '46007-11{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/460071105_sd.pdf', 'description': ', With thermal vias in pads', 'fp_name_suffix': '_ThermalVias', 'thermals': True, 'lock': False }, 'only_pads':{ 'mpn': '46007-11{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/460071105_sd.pdf', 'description': '', 'fp_name_suffix': '', 'thermals': False, 'lock': False } } def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 off = configuration['silk_fab_offset'] mpn = params['mpn'].format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, params['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # Dimensions P = (pins - 1) * pitch B = P + 2*6.79 # connector length W = 14.76 # connector width body_edge={} body_edge['left'] = (P-B)/2 body_edge['right'] = body_edge['left'] + B body_edge['top'] = 0.925 body_edge['bottom'] = body_edge['top'] + 14.76 bounding_box = body_edge.copy() bounding_box['top'] = -offset_second_pad - pad_size[1]/2 ################################## Pins ################################## kicad_mod.append(PadArray(pincount=pins, start=[0,0], x_spacing=pitch, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(pincount=pins, start=[0, -offset_second_pad], x_spacing=pitch, size=pad_size, drill=drill, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for xi in range(pins): n = xi + 1 pad_center_y = -offset_second_pad/2 pad_center_x = xi*pitch pad_h = offset_second_pad + pad_size[1] dx = (pad_size[0] - 2*thermal_to_pad_edge)/2 dy = (pad_h - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, y_spacing=dy*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x - dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x + dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) if params['lock']: kicad_mod.append(Pad(at=[-ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[P+ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -offset_second_pad-pad_size[1]/2], end=[pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) ############################ Outline ############################## #kicad_mod.append(RectLine(start=[xl1, yt1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=configuration['fab_line_width'])) if params['lock']: silk1 = [ {'x': -pad_size[0]/2 - pad_silk_off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': ret_dy-ret_size/2}, ] kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk1, layer='F.SilkS', width=configuration['silk_line_width'], x_mirror=P/2)) silk2 = [ {'x': body_edge['left']-off, 'y': ret_dy+ret_size/2}, {'x': body_edge['left']-off, 'y': body_edge['bottom']+off}, {'x': P/2, 'y': body_edge['bottom']+off}, ] kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=silk2, layer='F.SilkS', width=configuration['silk_line_width'], x_mirror=P/2)) else: kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], offset = off, layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins - 1): kicad_mod.append(Line( start=[i*pitch+pad_size[0]/2+pad_silk_off, body_edge['top']-off], end=[(i+1)*pitch-pad_size[0]/2-pad_silk_off, body_edge['top']-off], layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins): w_pin = 1 kicad_mod.append(RectLine(start=[i*pitch-w_pin/2, body_edge['top']], end=[i*pitch+w_pin/2, -offset_second_pad-drill/2], layer='F.Fab', width=configuration['fab_line_width'])) ############################ Pin 1 ################################ # Pin 1 designator pin1_sl = 2.4 pin1 = [ {'x': -pin1_sl/2, 'y': body_edge['top']}, {'x': 0, 'y': body_edge['top'] + pin1_sl/sqrt(2)}, {'x': pin1_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) pin1 = [ {'x': -pad_size[0]/2 - pad_silk_off, 'y': body_edge['top']-off}, {'x': -pad_size[0]/2 - pad_silk_off, 'y': -offset_second_pad-pad_size[1]/2} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) # pin1 = [ # {'x': 0, 'y': 8}, # {'x': 0.5, 'y': 9}, # {'x': -0.5, 'y': 9}, # {'x': 0, 'y': 8}, # ] # kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for version in version_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, version_params[version], configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_sabre_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "Sabre" series_long = 'Sabre Power Connector' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 #pins_per_row per row pins_per_row_range = [2, 3, 4, 5, 6] #Molex part number #n = number of circuits per row pitch = 7.49 drill = 1.78 offset_second_pad = 3.18 pad_to_pad_clearance = 3 max_annular_ring = 1 min_annular_ring = 0.15 #locating pins ret_dy = -offset_second_pad - 0.25 ret_dx = 4.75 ret_drill = 3.00 ret_size = 4.00 pad_size = [pitch - pad_to_pad_clearance, offset_second_pad + 0.25] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring version_params = { 'with_thermals_lock':{ 'mpn': '43160-21{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/431602102_sd.pdf', 'description': ', With thermal vias in pads', 'fp_name_suffix': '_ThermalVias', 'thermals': True, 'lock': True }, 'only_pads_lock':{ 'mpn': '43160-21{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/431602102_sd.pdf', 'description': '', 'fp_name_suffix': '', 'thermals': False, 'lock': True }, 'with_thermals':{ 'mpn': '43160-01{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/431600105_sd.pdf', 'description': ', With thermal vias in pads', 'fp_name_suffix': '_ThermalVias', 'thermals': True, 'lock': False }, 'only_pads':{ 'mpn': '43160-01{n:02d}', 'datasheet': 'http://www.molex.com/pdm_docs/sd/431600105_sd.pdf', 'description': '', 'fp_name_suffix': '', 'thermals': False, 'lock': False } } def generate_one_footprint(pins, params, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 off = configuration['silk_fab_offset'] mpn = params['mpn'].format(n=pins*number_of_rows) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name += params['fp_name_suffix'] kicad_mod = Footprint(footprint_name) desc_format_str = "Molex {:s}, {:s}{:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(desc_format_str.format(series_long, mpn, params['description'], pins, params['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # Dimensions P = (pins - 1) * pitch B = P + 2*6.79 # connector length W = 11.53 # connector width TW = 1.85 TL = 3.05 body_edge={} body_edge['left'] = (P-B)/2 body_edge['right'] = body_edge['left'] + B body_edge['top'] = -4.47 - offset_second_pad body_edge['bottom'] = body_edge['top'] + W bounding_box = body_edge.copy() bounding_box['top'] = body_edge['top'] - TW ################################## Pins ################################## kicad_mod.append(PadArray(pincount=pins, start=[0,0], x_spacing=pitch, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(pincount=pins, start=[0, -offset_second_pad], x_spacing=pitch, size=pad_size, drill=drill, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) d_small = 0.3 s_small = d_small + 2*min_annular_ring thermal_to_pad_edge = s_small/2 + 0.15 if params['thermals']: for xi in range(pins): n = xi + 1 pad_center_y = -offset_second_pad/2 pad_center_x = xi*pitch pad_h = offset_second_pad + pad_size[1] dx = (pad_size[0] - 2*thermal_to_pad_edge)/2 dy = (pad_h - 2*thermal_to_pad_edge)/4 #draw rectangle on F.Fab layer # kicad_mod.append(RectLine( # start=[pad_center_x - pad_l/2, pad_center_y - pad_size[1]/2], # end=[pad_center_x + pad_l/2, pad_center_y + pad_size[1]/2], # layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PadArray(center=[pad_center_x, pad_center_y], pincount=3, y_spacing=dy*2, drill=d_small, size=s_small, initial=n, increment=0, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x - dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) kicad_mod.append(PadArray(center=[pad_center_x + dx, pad_center_y], pincount=5, y_spacing=dy, drill=d_small, size=s_small, initial=n, increment=0, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, layers=Pad.LAYERS_THT)) if params['lock']: kicad_mod.append(Pad(at=[-ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(at=[P+ret_dx, ret_dy], type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, size=ret_size, drill=ret_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(RectLine(start=[-pad_size[0]/2, -offset_second_pad-pad_size[1]/2], end=[pad_size[0]/2,pad_size[1]/2],offset=pad_silk_off, width=configuration['silk_line_width'], layer='B.SilkS')) ############################ Outline ############################## #kicad_mod.append(RectLine(start=[xl1, yt1], end=[xr1, yb1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=configuration['fab_line_width'])) tab = [ {'x': P/2 - TL/2, 'y': body_edge['top']}, {'x': P/2 - TL/2, 'y': body_edge['top'] - TW}, {'x': P/2 + TL/2, 'y': body_edge['top'] - TW}, {'x': P/2 + TL/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=tab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(RectLine( start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], offset = off, layer='F.SilkS', width=configuration['silk_line_width'])) tab = [ {'x': P/2 - TL/2 - off, 'y': body_edge['top'] - off}, {'x': P/2 - TL/2 - off, 'y': body_edge['top'] - TW - off}, {'x': P/2 + TL/2 + off, 'y': body_edge['top'] - TW - off}, {'x': P/2 + TL/2 + off, 'y': body_edge['top'] - off} ] kicad_mod.append(PolygoneLine(polygone=tab, layer='F.SilkS', width=configuration['silk_line_width'])) ############################ Pin 1 ################################ # Pin 1 designator pin1_sl = 2.4 pin1 = [ {'x': -pin1_sl/2, 'y': body_edge['top']}, {'x': 0, 'y': body_edge['top'] + pin1_sl/sqrt(2)}, {'x': pin1_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.Fab', width=configuration['fab_line_width'])) pin1_sl = 0.8 yp1 = body_edge['top'] - off - 0.3 pin1 = [ {'x': 0,'y': yp1}, {'x': pin1_sl/2,'y': yp1-pin1_sl/sqrt(2)}, {'x': -pin1_sl/2,'y': yp1-pin1_sl/sqrt(2)}, {'x': 0,'y': yp1}, ] kicad_mod.append(PolygoneLine(polygone=pin1, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for version in version_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, version_params[version], configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_slimstack-501920.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SlimStack" series_long = 'SlimStack Fine-Pitch SMT Board-to-Board Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/5019204001_sd.pdf' #pins_per_row per row pins_range = [30,40,50] #Molex part number #n = number of circuits per row part_code = "501920-{n:02}01" pitch = 0.5 def generate_one_footprint(pincount, configuration): mpn = part_code.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = 0.5 pad_y_spacing = 2.4 + 1.1 pad_width = 0.3 pad_height = 1.1 pad_x_span = (pad_x_spacing * ((pincount / 2) - 1)) h_body_width = 3.1 / 2.0 h_body_length = (pad_x_span / 2.0) + 1.4 + 0.37 fab_width = configuration['fab_line_width'] outline_x = h_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.8 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(h_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,-pad_y_spacing/2.0], initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,pad_y_spacing/2.0], initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-h_body_length, -h_body_width], end=[h_body_length, h_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-h_body_length, 'top':-h_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-h_body_length+outline_x, -h_body_width-nudge], end=[-h_body_length+outline_x, -h_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-h_body_length+outline_x, h_body_width+nudge], [-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge, -h_body_width-nudge],\ [-h_body_length+outline_x, -h_body_width-nudge], [-h_body_length+outline_x, -h_body_width-marker_y]] right_outline = [[h_body_length-outline_x, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, -h_body_width-nudge],\ [h_body_length-outline_x, -h_body_width-nudge]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pins in pins_range: generate_one_footprint(pins, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_slimstack-502426.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, """ This family of parts is spread over 2 datasheets, depending on the 3rd number in the PN suffix: 502340-xx10 (8-80 pin): http://www.molex.com/pdm_docs/sd/5024260810_sd.pdf 502340-xx30 (14-80 pin): http://www.molex.com/pdm_docs/sd/5024261430_sd.pdf """ import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SlimStack" series_long = 'SlimStack Fine-Pitch SMT Board-to-Board Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 #pins_per_row per row valid_pns = [ "0810","1410","2010","2210","2410","2610","3010","3210","3410","4010","4410","5010","6010","6410","8010", #"1430","2030","2230","2430","2630","3030","3230","4030","5030","6030","7030","8030" ] #Molex part number #n = number of circuits per row part_code = "502426-{pn:s}" pitch = 0.4 def generate_one_footprint(partnumber, configuration): pincount = int(partnumber[:2]) if partnumber[2:3] == "1": datasheet = "http://www.molex.com/pdm_docs/sd/5024260810_sd.pdf" elif partnumber[2:3] == "3": datasheet = "http://www.molex.com/pdm_docs/sd/5024261430_sd.pdf" mpn = part_code.format(pn=partnumber) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = pitch pad_y_spacing = 1.95 + 0.475 pad_width = 0.22 pad_height = 0.475 pad_x_span = pad_x_spacing * ((pincount / 2) - 1) nail_x = pad_x_span / 2.0 + 0.95 nail_y = 1.085 nail_width = 0.32 nail_height = 0.65 half_body_width = 2.6 / 2.0 half_body_length = (pad_x_span / 2.0) + 1.75 fab_width = configuration['fab_line_width'] outline_x = half_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.2 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(half_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=-pad_x_spacing, y_spacing=0,center=[0,-pad_y_spacing/2.0],\ initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=-pad_x_spacing, y_spacing=0,center=[0,pad_y_spacing/2.0],\ initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],layers=Pad.LAYERS_SMT)) # create "fitting nail" (npth mounting) holes #kicad_mod.append(Pad(at=[-nail_x, 0], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_RECT, size=[0.35, 0.44], drill=[0.35, 0.44], layers=['*.Cu', '*.Mask'])) #kicad_mod.append(Pad(at=[nail_x, 0], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_RECT, size=[0.35, 0.44], drill=[0.35, 0.44], layers=['*.Cu', '*.Mask'])) kicad_mod.append(RectLine(start=[-nail_x - nail_width / 2.0, -nail_y - nail_height / 2.0], end=[-nail_x + nail_width / 2.0, -nail_y + nail_height / 2.0], layer='Edge.Cuts', width=fab_width)) kicad_mod.append(RectLine(start=[-nail_x - nail_width / 2.0, nail_y - nail_height / 2.0], end=[-nail_x + nail_width / 2.0, nail_y + nail_height / 2.0], layer='Edge.Cuts', width=fab_width)) kicad_mod.append(RectLine(start=[nail_x - nail_width / 2.0, -nail_y - nail_height / 2.0], end=[nail_x + nail_width / 2.0, -nail_y + nail_height / 2.0], layer='Edge.Cuts', width=fab_width)) kicad_mod.append(RectLine(start=[nail_x - nail_width / 2.0, nail_y - nail_height / 2.0], end=[nail_x + nail_width / 2.0, nail_y + nail_height / 2.0], layer='Edge.Cuts', width=fab_width)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-half_body_length, -half_body_width], end=[half_body_length, half_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-half_body_length, 'top':-half_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[half_body_length-outline_x, -half_body_width], end=[half_body_length-outline_x, -half_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-half_body_length+outline_x, half_body_width+nudge], [-half_body_length-nudge, half_body_width+nudge], [-half_body_length-nudge, -half_body_width-nudge],\ [-half_body_length+outline_x, -half_body_width-nudge]] right_outline = [[half_body_length-outline_x, half_body_width+nudge], [half_body_length+nudge, half_body_width+nudge], [half_body_length+nudge, -half_body_width-nudge],\ [half_body_length-outline_x, -half_body_width-nudge], [half_body_length-outline_x, -half_body_width-marker_y]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for partnumber in valid_pns: generate_one_footprint(partnumber, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_slimstack-502430.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, """ This family of parts is spread over 3 datasheets, depending on the 3rd number in the PN suffix: 502340-xx10 (14-80 pin): http://www.molex.com/pdm_docs/sd/5024301410_sd.pdf 502340-0820 (8 pin) http://www.molex.com/pdm_docs/sd/5024300820_sd.pdf 502340-xx30 (14-90 pin): http://www.molex.com/pdm_docs/sd/5024307030_sd.pdf """ import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SlimStack" series_long = 'SlimStack Fine-Pitch SMT Board-to-Board Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 #pins_per_row per row valid_pns = [ "1410","2010","2210","2410","2610","3010","3210","3410","4010","4410","5010","6010","6410","8010", "0820", #"1430","2030","2230","2430","2630","3230","4030","5030","6030","7030","8030","9030" ] #Molex part number #n = number of circuits per row part_code = "502430-{pn:s}" pitch = 0.4 def generate_one_footprint(partnumber, configuration): pincount = int(partnumber[:2]) if str(partnumber)[2:3] == "1": datasheet = "http://www.molex.com/pdm_docs/sd/5024301410_sd.pdf" elif str(partnumber)[2:3] == "2": datasheet = "http://www.molex.com/pdm_docs/sd/5024300820_sd.pdf" elif str(partnumber)[2:3] == "3": datasheet = "http://www.molex.com/pdm_docs/sd/5024307030_sd.pdf" mpn = part_code.format(pn=partnumber) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = pitch pad_y_spacing = 1.05 + 0.66 pad_width = 0.22 pad_height = 0.66 pad_x_span = pad_x_spacing * ((pincount / 2) - 1) nail_x = pad_x_span / 2.0 + 0.95 half_body_width = 1.54 / 2.0 half_body_length = (pad_x_span / 2.0) + 1.33 fab_width = configuration['fab_line_width'] outline_x = half_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.35 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(half_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,center=[0,-pad_y_spacing/2.0],\ initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,center=[0,pad_y_spacing/2.0],\ initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],layers=Pad.LAYERS_SMT)) # create "fitting nail" (npth mounting) holes #kicad_mod.append(Pad(at=[-nail_x, 0], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_RECT, size=[0.35, 0.44], drill=[0.35, 0.44], layers=['*.Cu', '*.Mask'])) #kicad_mod.append(Pad(at=[nail_x, 0], type=Pad.TYPE_NPTH, shape=Pad.SHAPE_RECT, size=[0.35, 0.44], drill=[0.35, 0.44], layers=['*.Cu', '*.Mask'])) kicad_mod.append(RectLine(start=[-nail_x - 0.35 / 2.0, -0.22], end=[-nail_x + 0.35 / 2.0, 0.22], layer='Edge.Cuts', width=fab_width)) kicad_mod.append(RectLine(start=[nail_x - 0.35 / 2.0, -0.22], end=[nail_x + 0.35 / 2.0, 0.22], layer='Edge.Cuts', width=fab_width)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-half_body_length, -half_body_width], end=[half_body_length, half_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-half_body_length, 'top':-half_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-half_body_length+outline_x, -half_body_width], end=[-half_body_length+outline_x, -half_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-half_body_length+outline_x, half_body_width+nudge], [-half_body_length-nudge, half_body_width+nudge], [-half_body_length-nudge, -half_body_width-nudge],\ [-half_body_length+outline_x, -half_body_width-nudge], [-half_body_length+outline_x, -half_body_width-marker_y]] right_outline = [[half_body_length-outline_x, half_body_width+nudge], [half_body_length+nudge, half_body_width+nudge], [half_body_length+nudge, -half_body_width-nudge],\ [half_body_length-outline_x, -half_body_width-nudge]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for partnumber in valid_pns: generate_one_footprint(partnumber, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_slimstack-52991.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SlimStack" series_long = 'SlimStack Fine-Pitch SMT Board-to-Board Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/529910308_sd.pdf' #pins_per_row per row pins_range = [20,30,40,50,60,70,80] #Molex part number #n = number of circuits per row part_code = "52991-0{n:02}8" pitch = 0.5 def generate_one_footprint(pincount, configuration): mpn = part_code.format(n=pincount) CrtYd_off = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] body_edge = {} bounding_box = {} # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = pitch pad_y_spacing = 2.2 + 1.8 pad_width = 0.3 pad_height = 1.8 pad_x_span = (pad_x_spacing * ((pincount / 2) - 1)) h_body_width = 4.3 / 2.0 h_body_length = (pad_x_span / 2.0) + 2.15 tab_width = 1.3 tab_height = 0.5 fab_width = configuration['fab_line_width'] outline_x = h_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.8 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(h_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,-pad_y_spacing/2.0], initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,pad_y_spacing/2.0], initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-h_body_length, -h_body_width], end=[h_body_length, h_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-h_body_length, 'top':-h_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-h_body_length+outline_x, -h_body_width-nudge], end=[-h_body_length+outline_x, -h_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-h_body_length+outline_x, h_body_width+nudge], [-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge, -h_body_width-nudge],\ [-h_body_length+outline_x, -h_body_width-nudge], [-h_body_length+outline_x, -h_body_width-marker_y]] right_outline = [[h_body_length-outline_x, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, -h_body_width-nudge],\ [h_body_length-outline_x, -h_body_width-nudge]] top_left_tab = [[-h_body_length-nudge, -h_body_width-nudge], [-h_body_length-nudge, -h_body_width-nudge-tab_height],\ [-h_body_length-nudge+tab_width, -h_body_width-nudge-tab_height], [-h_body_length-nudge+tab_width, -h_body_width-nudge]] bottom_left_tab = [[-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge+tab_width/3, h_body_width+nudge+tab_height],\ [-h_body_length-nudge+tab_width, h_body_width+nudge+tab_height], [-h_body_length-nudge+tab_width, h_body_width+nudge]] top_right_tab = [[h_body_length+nudge, -h_body_width-nudge], [h_body_length+nudge, -h_body_width-nudge-tab_height],\ [h_body_length+nudge-tab_width, -h_body_width-nudge-tab_height], [h_body_length+nudge-tab_width, -h_body_width-nudge]] bottom_right_tab = [[h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge+tab_height],\ [h_body_length+nudge-tab_width, h_body_width+nudge+tab_height], [h_body_length+nudge-tab_width, h_body_width+nudge]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=top_left_tab, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=bottom_left_tab, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=top_right_tab, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=bottom_right_tab, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pins in pins_range: generate_one_footprint(pins, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_slimstack-53748.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import math from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SlimStack" series_long = 'SlimStack Fine-Pitch SMT Board-to-Board Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'https://www.molex.com/pdm_docs/sd/537480308_sd.pdf' #pins_per_row per row pins_range = [20,30,40,60,70,80] #Molex part number #n = number of circuits per row part_code = "53748-0{n:02}8" pitch = 0.5 def generate_one_footprint(pincount, configuration): mpn = part_code.format(n=pincount) CrtYd_off = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] body_edge = {} bounding_box = {} # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = 2.2 + 1.2 pad_y_spacing = pitch pad_width = 1.2 pad_height = 0.3 pad_y_span = (pad_y_spacing * ((pincount / 2) - 1)) h_body_width = 3.1 / 2.0 h_body_length = (pad_y_span / 2.0) + 2.15 tab_width = 0.6 tab_height = 1.1 tab_cut_x = 0.49 tab_cut_y = 0.7 silk_tab_cut_offset_x = configuration['silk_fab_offset']*math.tan(math.radians(55/2)) silk_tab_cut_offset_y = configuration['silk_fab_offset']*math.tan(math.radians(35/2)) fab_width = configuration['fab_line_width'] outline_y = pad_y_span / 2.0 + pad_height/2 + (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_x = 0.7 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(max(h_body_width + tab_width, (pad_x_spacing + pad_width)/2) + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase(h_body_length + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=0, y_spacing=pad_y_spacing,\ center=[-pad_x_spacing/2.0, 0], initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=0, y_spacing=pad_y_spacing,\ center=[pad_x_spacing/2.0, 0], initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker fab_outline = [[-h_body_width - tab_width, -h_body_length], \ [-h_body_width - tab_width, -h_body_length + tab_height], [-h_body_width, -h_body_length + tab_height], \ [-h_body_width, h_body_length - tab_height], [-h_body_width - tab_width, h_body_length - tab_height], \ [-h_body_width - tab_width, h_body_length - tab_cut_y], [-h_body_width - tab_width + tab_cut_x, h_body_length], \ [h_body_width + tab_width, h_body_length], [h_body_width + tab_width, h_body_length - tab_height], [h_body_width, h_body_length - tab_height], [h_body_width, -h_body_length + tab_height], \ [h_body_width + tab_width, -h_body_length + tab_height], [h_body_width + tab_width, -h_body_length], \ [-h_body_width - tab_width, -h_body_length]] kicad_mod.append(PolygoneLine(polygone=fab_outline, layer='F.Fab', width=fab_width)) body_edge={ 'left':-h_body_width, 'top':-h_body_length } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-h_body_width+marker_x, -pad_y_span/2], end=[-h_body_width, -pad_y_span/2+marker_x/2], layer='F.Fab', width=fab_width)) kicad_mod.append(Line(start=[-h_body_width+marker_x, -pad_y_span/2], end=[-h_body_width, -pad_y_span/2-marker_x/2], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker top_outline = [[h_body_width+nudge, -outline_y], [h_body_width+nudge, -h_body_length+nudge+tab_height], \ [h_body_width+nudge+tab_width, -h_body_length+nudge+tab_height], [h_body_width+nudge+tab_width, -h_body_length-nudge], \ [-h_body_width-nudge-tab_width, -h_body_length-nudge], [-h_body_width-nudge-tab_width, -h_body_length+nudge+tab_height], \ [-h_body_width-nudge-tab_width, -h_body_length+nudge+tab_height], [-h_body_width-nudge, -h_body_length+nudge+tab_height], \ [-h_body_width-nudge, -outline_y], [-h_body_width-marker_x, -outline_y]] bottom_outline = [[h_body_width+nudge, outline_y], [h_body_width+nudge, h_body_length-nudge-tab_height], \ [h_body_width+nudge+tab_width, h_body_length-nudge-tab_height], [h_body_width+nudge+tab_width, h_body_length+nudge], \ [-h_body_width - tab_width + tab_cut_x - silk_tab_cut_offset_x,+h_body_length+nudge], [-h_body_width-nudge-tab_width, h_body_length - tab_cut_y + silk_tab_cut_offset_y],\ [-h_body_width-nudge-tab_width, h_body_length-nudge-tab_height], [-h_body_width - nudge, h_body_length-nudge-tab_height], \ [-h_body_width-nudge, outline_y]] kicad_mod.append(PolygoneLine(polygone=top_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=bottom_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center', allow_rotation=True) ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pins in pins_range: generate_one_footprint(pins, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_slimstack-54722.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SlimStack" series_long = 'SlimStack Fine-Pitch SMT Board-to-Board Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/547220804_sd.pdf' #pins_per_row per row pins_range = [16,20,22,24,30,34,40,50,60,80] #Molex part number #n = number of circuits per row part_code = "54722-0{n:02}4" pitch = 0.5 def generate_one_footprint(pincount, configuration): mpn = part_code.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = pitch pad_y_spacing = 4.4 + 1.1 pad_width = 0.3 pad_height = 1.1 pad_x_span = (pad_x_spacing * ((pincount / 2) - 1)) h_body_width = 5.0 / 2.0 h_body_length = (pad_x_span / 2.0) + 1.05 + 0.5 fab_width = configuration['fab_line_width'] #outline_x = 1.2 outline_x = h_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.8 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(h_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,-pad_y_spacing/2.0], initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,pad_y_spacing/2.0], initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-h_body_length, -h_body_width], end=[h_body_length, h_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-h_body_length, 'top':-h_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-h_body_length+outline_x, -h_body_width-nudge], end=[-h_body_length+outline_x, -h_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-h_body_length+outline_x, h_body_width+nudge], [-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge, -h_body_width-nudge],\ [-h_body_length+outline_x, -h_body_width-nudge], [-h_body_length+outline_x, -h_body_width-marker_y]] right_outline = [[h_body_length-outline_x, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, -h_body_width-nudge],\ [h_body_length-outline_x, -h_body_width-nudge]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pins in pins_range: generate_one_footprint(pins, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_slimstack-55560.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SlimStack" series_long = 'SlimStack Fine-Pitch SMT Board-to-Board Connectors' manufacturer = 'Molex' orientation = 'V' number_of_rows = 2 datasheet = 'http://www.molex.com/pdm_docs/sd/555600207_sd.pdf' #pins_per_row per row pins_range = [16,20,22,24,30,34,40,50,60,80] #Molex part number #n = number of circuits per row part_code = "55560-0{n:02}1" pitch = 0.5 def generate_one_footprint(pincount, configuration): mpn = part_code.format(n=pincount) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount//2, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) kicad_mod.setAttribute('smd') # calculate working values pad_x_spacing = pitch pad_y_spacing = 2.9 + 1.0 pad_width = 0.3 pad_height = 1.0 pad_x_span = (pad_x_spacing * ((pincount / 2) - 1)) h_body_width = 2.83 / 2.0 h_body_length = (pad_x_span / 2.0) + 0.45 + 0.525 fab_width = configuration['fab_line_width'] #outline_x = 0.6 outline_x = h_body_length - (pad_x_span / 2.0) - pad_width/2 - (configuration['silk_pad_clearance'] + configuration['silk_line_width']/2) marker_y = 0.8 silk_width = configuration['silk_line_width'] nudge = configuration['silk_fab_offset'] courtyard_width = configuration['courtyard_line_width'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(h_body_length + courtyard_clearance, courtyard_precision) courtyard_y = roundToBase((pad_y_spacing + pad_height) / 2.0 + courtyard_clearance, courtyard_precision) # create pads kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,-pad_y_spacing/2.0], initial=1, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(pincount=pincount//2, x_spacing=pad_x_spacing, y_spacing=0,\ center=[0,pad_y_spacing/2.0], initial=2, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height],\ layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker kicad_mod.append(RectLine(start=[-h_body_length, -h_body_width], end=[h_body_length, h_body_width], layer='F.Fab', width=fab_width)) body_edge={ 'left':-h_body_length, 'top':-h_body_width } body_edge['right'] = -body_edge['left'] body_edge['bottom'] = -body_edge['top'] kicad_mod.append(Line(start=[-h_body_length+outline_x, -h_body_width-nudge], end=[-h_body_length+outline_x, -h_body_width-marker_y], layer='F.Fab', width=fab_width)) # create silkscreen outline and pin 1 marker left_outline = [[-h_body_length+outline_x, h_body_width+nudge], [-h_body_length-nudge, h_body_width+nudge], [-h_body_length-nudge, -h_body_width-nudge],\ [-h_body_length+outline_x, -h_body_width-nudge], [-h_body_length+outline_x, -h_body_width-marker_y]] right_outline = [[h_body_length-outline_x, h_body_width+nudge], [h_body_length+nudge, h_body_width+nudge], [h_body_length+nudge, -h_body_width-nudge],\ [h_body_length-outline_x, -h_body_width-nudge]] kicad_mod.append(PolygoneLine(polygone=left_outline, layer='F.SilkS', width=silk_width)) kicad_mod.append(PolygoneLine(polygone=right_outline, layer='F.SilkS', width=silk_width)) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, -courtyard_y], end=[courtyard_x, courtyard_y], layer='F.CrtYd', width=courtyard_width)) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-courtyard_y, 'bottom':+courtyard_y}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pins in pins_range: generate_one_footprint(pins, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/conn_molex_stackable-linear_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SL" series_long = 'Stackable Linear Connector' manufacturer = 'Molex' orientation = 'V' number_of_rows = 1 #pins_per_row_per_row per row pins_per_row_range = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] #Molex part number #n = number of circuits per row # Boss ist ohne zusätzliche Befestigungslöcher. Dafür gibt es eine komische zusätzliche Bohrung variant_params = { 'boss':{ 'mount_pins': False, 'datasheet': 'https://www.molex.com/pdm_docs/sd/1719710002_sd.pdf', 'part_code': "171971-00{n:02d}", 'alternative_codes': [ "171971-01{n:02d}", "171971-02{n:02d}" ] } } pitch = 2.54 drill = 1.09 start_pos_x = 0 # Where should pin 1 be located. pad_to_pad_clearance = 0.8 max_annular_ring = 0.95 #How much copper should be in y direction? min_annular_ring = 0.15 row = 2.54 size = row - pad_to_pad_clearance if size - drill < 2 * min_annular_ring: size = drill + 2 * min_annular_ring if size - drill > 2 * max_annular_ring: size = drill + 2 * max_annular_ring # print("size", size) def generate_one_footprint(pins_per_row, variant, configuration): mpn = variant_params[variant]['part_code'].format(n = pins_per_row) alt_mpn = [code.format(n=pins_per_row) for code in variant_params[variant]['alternative_codes']] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man = manufacturer, series = series, mpn = mpn, num_rows = number_of_rows, pins_per_row = pins_per_row, mounting_pad = "", pitch = pitch, orientation = orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Molex {:s}, {:s} (compatible alternatives: {:s}), {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, ', '.join(alt_mpn), pins_per_row, variant_params[variant]['datasheet'])) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation = orientation_str, man = manufacturer, entry = configuration['entry_direction'][orientation])) #calculate fp dimensions #connector length if pins_per_row == 2: A = 7.38 else: A = pins_per_row * pitch + 2.46 #pin centers P = (pins_per_row - 1) * pitch #connector width W = 5.1 #corner positions x1 = -(A - P) / 2 x2 = x1 + A y2 = W / 2 y1 = y2 - W #tab length if pins_per_row == 2: tab_l = 6.86 else: tab_l = 7.62 #tab width tab_w = 1.50 body_edge = { 'left': x1, 'right': x2, 'bottom': y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['bottom'] = y2 + tab_w optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT #generate the pads kicad_mod.append(PadArray( pincount = pins_per_row, initial = 1, start = [0, 0], x_spacing=pitch, type = Pad.TYPE_THT, shape = Pad.SHAPE_CIRCLE, size = size, drill = drill, layers = Pad.LAYERS_THT, **optional_pad_params)) off = configuration['silk_fab_offset'] silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width'] / 2 #draw the outline of the shape kicad_mod.append(PolygoneLine(polygone = [ { 'x': body_edge['left'], 'y': body_edge['top'] }, { 'x': body_edge['left'], 'y': body_edge['top'] + 2.31 }, { 'x': body_edge['left'] + 0.13, 'y': body_edge['top'] + 2.31 }, { 'x': body_edge['left'] + 0.13, 'y': body_edge['bottom'] - 0.76 }, { 'x': body_edge['left'], 'y': body_edge['bottom'] - 0.76 }, { 'x': body_edge['left'], 'y': body_edge['bottom'] }, { 'x': body_edge['right'], 'y': body_edge['bottom'] }, { 'x': body_edge['right'], 'y': body_edge['bottom'] - 0.76 }, { 'x': body_edge['right'] - 0.13, 'y': body_edge['bottom'] - 0.76 }, { 'x': body_edge['right'] - 0.13, 'y': body_edge['top'] + 2.31 }, { 'x': body_edge['right'], 'y': body_edge['top'] + 2.31 }, { 'x': body_edge['right'], 'y': body_edge['top'] }, { 'x': body_edge['left'], 'y': body_edge['top'] }, ], layer = 'F.Fab', width = configuration['fab_line_width'])) #draw the outline of the tab kicad_mod.append(PolygoneLine(polygone = [ { 'x': P / 2 - tab_l / 2,'y': y2} , { 'x': P / 2 - tab_l / 2,'y': y2 + tab_w }, { 'x': P / 2 + tab_l / 2,'y': y2 + tab_w }, { 'x': P / 2 + tab_l / 2,'y': y2 }, ], layer = 'F.Fab', width = configuration['fab_line_width'])) #draw the outline of the connector on the silkscreen kicad_mod.append(PolygoneLine(polygone = [ { 'x': body_edge['left'] - off, 'y': body_edge['top'] - off }, { 'x': body_edge['left'] - off, 'y': body_edge['top'] + 2.31 + off }, { 'x': body_edge['left'] + 0.13 - off, 'y': body_edge['top'] + 2.31 + off }, { 'x': body_edge['left'] + 0.13 - off, 'y': body_edge['bottom'] - 0.76 - off }, { 'x': body_edge['left'] - off, 'y': body_edge['bottom'] - 0.76 - off }, { 'x': body_edge['left'] - off, 'y': body_edge['bottom'] + off }, { 'x': P / 2 - tab_l / 2 - off, 'y': y2 + off} , { 'x': P / 2 - tab_l / 2 - off, 'y': y2 + tab_w + off }, { 'x': P / 2 + tab_l / 2 + off,'y': y2 + tab_w + off }, { 'x': P / 2 + tab_l / 2 + off,'y': y2 + off}, { 'x': body_edge['right'] + off, 'y': body_edge['bottom'] + off }, { 'x': body_edge['right'] + off, 'y': body_edge['bottom'] - 0.76 - off }, { 'x': body_edge['right'] - 0.13 + off, 'y': body_edge['bottom'] - 0.76 - off }, { 'x': body_edge['right'] - 0.13 + off, 'y': body_edge['top'] + 2.31 + off }, { 'x': body_edge['right'] + off, 'y': body_edge['top'] + 2.31 + off }, { 'x': body_edge['right'] + off, 'y': body_edge['top'] - off }, { 'x': body_edge['left'] - off, 'y': body_edge['top'] - off }, ], layer = 'F.SilkS', width = configuration['silk_line_width'])) #pin-1 marker p1m_off = 0.3 + off p1m_sl = 2 pin = [ { 'x': body_edge['left'] - p1m_off, 'y': body_edge['top'] + p1m_sl }, { 'x': body_edge['left'] - p1m_off, 'y': body_edge['top'] - p1m_off }, { 'x': body_edge['left'] + p1m_sl, 'y': body_edge['top'] - p1m_off }, ] kicad_mod.append(PolygoneLine(polygone = pin, layer = 'F.SilkS', width = configuration['silk_line_width'])) sl = 1 pin = [ {'y': body_edge['top'], 'x': sl / 2 }, {'y': body_edge['top'] + sl / sqrt(2), 'x': 0 }, {'y': body_edge['top'], 'x': -sl / 2 } ] kicad_mod.append(PolygoneLine(polygone = pin, width = configuration['fab_line_width'], layer = 'F.Fab')) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top'] - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) if variant_params[variant]['mount_pins']: pass else: kicad_mod.append(RectLine( start = [cx1, cy1], end = [cx2, cy2], layer = 'F.CrtYd', width = configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod = kicad_mod, configuration = configuration, body_edges = body_edge, courtyard = { 'top': cy1, 'bottom': cy2 }, fp_name = footprint_name, text_y_inside_position = 'bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix = model3d_path_prefix, lib_name = lib_name, fp_name = footprint_name) kicad_mod.append(Model(filename = model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name = lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir = output_dir, fp_name = footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Molex/helpers.py ================================================ def roundToBase(value, base): if base == 0: return value return round(value/base) * base ================================================ FILE: scripts/Connector/Connector_PCBEdge/molex_EDGELOCK.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) from KicadModTree import * padNums = [2, 4, 6, 8] datasheet = "https://www.molex.com/pdm_docs/sd/2008900106_sd.pdf" leftSpaceWidth = 2.2 rightSpaceWidth = 1.4 spaceHeight = 7.1 centerSpaceHeight = 4.2 centerSpaceWidth = 0.85 centerCardWidth = 5.4 edgeToHoleBottom = 5.25 holeWidth = 2.8 holeHeight = 3.05 edgeToPadBottom = 0.9 edgeToPadTop = spaceHeight padWidth = 1.0 padHeight = edgeToPadTop - edgeToPadBottom padToPad = 2.0 padCenterToSpaceSide = 1.1 datasheetCDiffB = 0.3 datasheetBtoHousingLeft = 1.9 datasheetBtoHousingRight = 1.0 largerR = 0.4 smallerR = 0.2 chamferLength = 0.5 chamferComment = "Chamfer 30 degree " + str(chamferLength) + " mm" housingHeight = 20.8 for padNum in padNums: footprint_name = "molex_EDGELOCK_" + str(padNum) + "-CKT" datasheetC = centerCardWidth + centerSpaceWidth * 2 + padCenterToSpaceSide * 4 + (padNum - 2) * padToPad datasheetB = datasheetC + datasheetCDiffB housingWidth = datasheetB + datasheetBtoHousingLeft + datasheetBtoHousingRight edgeToHousingTop = edgeToHoleBottom + holeHeight f = Footprint(footprint_name) f.setDescription(datasheet) f.setTags("Connector PCBEdge molex EDGELOCK") f.setAttribute("smd") f.append(Model(filename="${KISYS3DMOD}/Connector_PCBEdge.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) s = [1.0, 1.0] sFabRef = [0.7, 0.7] t1 = 0.1 t2 = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 wCut = wSilkS crtYd = 0.3 silkClearance = 0.2 bevelLength = 1.0 xCenter = 0.0 xFabRight = housingWidth / 2 xSilkRight = xFabRight + silkClearance xRightCrtYd = xSilkRight + crtYd xLeftCrtYd = - xRightCrtYd xFabLeft = -xFabRight xSilkLeft = -xSilkRight xOffset = (datasheetBtoHousingLeft - datasheetBtoHousingRight) / 2 xFabRight -= xOffset xSilkRight -= xOffset xRightCrtYd -= xOffset xLeftCrtYd -= xOffset xFabLeft -= xOffset xSilkLeft -= xOffset yCenter = 0.0 yFabBottom = housingHeight / 2 yFabTop = -yFabBottom yEdge = yFabTop + edgeToHousingTop ySilkBottom = yEdge - spaceHeight yBottomCrtYd = yEdge ySilkTop = yFabTop - silkClearance yTopCrtYd = ySilkTop - crtYd yValue = yFabBottom + 1.25 yRef = yFabTop - 1.25 yOffset = yEdge - edgeToPadBottom - padHeight / 2 yFabBottom -= yOffset yFabTop -= yOffset yEdge -= yOffset ySilkBottom -= yOffset yBottomCrtYd -= yOffset ySilkTop -= yOffset yTopCrtYd -= yOffset yValue -= yOffset yRef -= yOffset f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s, thickness=t2)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s, thickness=t2)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=sFabRef, thickness=t1)) f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) f.append(PolygoneLine(polygone=[[xFabRight, yFabTop], [xFabRight, yFabBottom], [xFabLeft, yFabBottom], [xFabLeft, yFabTop + bevelLength], [xFabLeft + bevelLength, yFabTop], [xFabRight, yFabTop]], layer="F.Fab", width=wFab)) f.append(PolygoneLine(polygone=[[xSilkLeft, ySilkBottom], [xSilkLeft, ySilkTop + bevelLength], [xSilkLeft + bevelLength, ySilkTop], [xSilkRight, ySilkTop], [xSilkRight, ySilkBottom]], layer="F.SilkS", width=wSilkS)) padShape = Pad.SHAPE_ROUNDRECT radiusRatio = 0.2 padSize = [padWidth, padHeight] yPad = yEdge - edgeToPadBottom - padHeight / 2 xPadLeft = xFabLeft + datasheetBtoHousingLeft + padCenterToSpaceSide + datasheetCDiffB / 2 for i in range(0, padNum): x = xPadLeft + padToPad * i if (i >= padNum/2): x += centerCardWidth + centerSpaceWidth * 2 + padCenterToSpaceSide * 2 - padToPad f.append(Pad(number=i+1, type=Pad.TYPE_SMT, shape=padShape, at=[x, yPad], size=padSize, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) padCardWidth = padToPad * (padNum / 2 - 1) + padCenterToSpaceSide * 2 xSpaceLeftRight = xFabLeft + datasheetBtoHousingLeft + datasheetCDiffB / 2 xSpaceCneterLeftLeft = xSpaceLeftRight + padCardWidth xSpaceCneterRightLeft = xSpaceCneterLeftLeft + centerSpaceWidth + centerCardWidth xSpaceRightLeft = xSpaceCneterRightLeft + centerSpaceWidth + padCardWidth f.append(PolygoneLine(polygone=[[xSpaceLeftRight - leftSpaceWidth, yEdge], [xSpaceLeftRight - leftSpaceWidth, yEdge - spaceHeight + largerR]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceLeftRight - leftSpaceWidth + largerR, yEdge - spaceHeight + largerR], start=[xSpaceLeftRight - leftSpaceWidth, yEdge - spaceHeight + largerR], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceLeftRight - leftSpaceWidth + largerR, yEdge - spaceHeight], [xSpaceLeftRight - largerR, yEdge - spaceHeight]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceLeftRight - largerR, yEdge - spaceHeight + largerR], start=[xSpaceLeftRight - largerR, yEdge - spaceHeight], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceLeftRight, yEdge - spaceHeight + largerR], [xSpaceLeftRight, yEdge], [xSpaceCneterLeftLeft, yEdge], [xSpaceCneterLeftLeft, yEdge - centerSpaceHeight + smallerR]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceCneterLeftLeft + smallerR, yEdge - centerSpaceHeight + smallerR], start=[xSpaceCneterLeftLeft, yEdge - centerSpaceHeight + smallerR], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceCneterLeftLeft + smallerR, yEdge - centerSpaceHeight], [xSpaceCneterLeftLeft + centerSpaceWidth - smallerR, yEdge - centerSpaceHeight]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceCneterLeftLeft + centerSpaceWidth - smallerR, yEdge - centerSpaceHeight + smallerR], start=[xSpaceCneterLeftLeft + centerSpaceWidth - smallerR, yEdge - centerSpaceHeight], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceCneterLeftLeft + centerSpaceWidth, yEdge - centerSpaceHeight + smallerR], [xSpaceCneterLeftLeft + centerSpaceWidth, yEdge], [xSpaceCneterRightLeft, yEdge], [xSpaceCneterRightLeft, yEdge - centerSpaceHeight + smallerR]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceCneterRightLeft + smallerR, yEdge - centerSpaceHeight + smallerR], start=[xSpaceCneterRightLeft, yEdge - centerSpaceHeight + smallerR], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceCneterRightLeft + smallerR, yEdge - centerSpaceHeight], [xSpaceCneterRightLeft + centerSpaceWidth - smallerR, yEdge - centerSpaceHeight]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceCneterRightLeft + centerSpaceWidth - smallerR, yEdge - centerSpaceHeight + smallerR], start=[xSpaceCneterRightLeft + centerSpaceWidth - smallerR, yEdge - centerSpaceHeight], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceCneterRightLeft + centerSpaceWidth, yEdge - centerSpaceHeight + smallerR], [xSpaceCneterRightLeft + centerSpaceWidth, yEdge], [xSpaceRightLeft, yEdge], [xSpaceRightLeft, yEdge - spaceHeight + largerR]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceRightLeft + largerR, yEdge - spaceHeight + largerR], start=[xSpaceRightLeft, yEdge - spaceHeight + largerR], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceRightLeft + largerR, yEdge - spaceHeight], [xSpaceRightLeft + rightSpaceWidth - largerR, yEdge - spaceHeight]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xSpaceRightLeft + rightSpaceWidth - largerR, yEdge - spaceHeight + largerR], start=[xSpaceRightLeft + rightSpaceWidth - largerR, yEdge - spaceHeight], angle=90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceRightLeft + rightSpaceWidth, yEdge - spaceHeight + largerR], [xSpaceRightLeft + rightSpaceWidth, yEdge]], layer="Edge.Cuts", width=wCut)) xHoleLeft = xSpaceCneterLeftLeft + centerSpaceWidth + (centerCardWidth - holeWidth) / 2 yHoleBottom = yEdge - edgeToHoleBottom f.append(Arc(center=[xHoleLeft + largerR, yHoleBottom - largerR], start=[xHoleLeft, yHoleBottom - largerR], angle=-90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xHoleLeft + largerR, yHoleBottom], [xHoleLeft + holeWidth - largerR, yHoleBottom]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xHoleLeft + holeWidth - largerR, yHoleBottom - largerR], start=[xHoleLeft + holeWidth - largerR, yHoleBottom], angle=-90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xHoleLeft + holeWidth, yHoleBottom - largerR], [xHoleLeft + holeWidth, yHoleBottom - holeHeight + largerR]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xHoleLeft + holeWidth - largerR, yHoleBottom - holeHeight + largerR], start=[xHoleLeft + holeWidth, yHoleBottom - holeHeight + largerR], angle=-90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xHoleLeft + holeWidth - largerR, yHoleBottom - holeHeight], [xHoleLeft + largerR, yHoleBottom - holeHeight]], layer="Edge.Cuts", width=wCut)) f.append(Arc(center=[xHoleLeft + largerR, yHoleBottom - holeHeight + largerR], start=[xHoleLeft + largerR, yHoleBottom - holeHeight], angle=-90.0, layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xHoleLeft, yHoleBottom - holeHeight + largerR], [xHoleLeft, yHoleBottom - largerR]], layer="Edge.Cuts", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceLeftRight, yEdge - chamferLength], [xSpaceCneterLeftLeft, yEdge - chamferLength]], layer="Dwgs.User", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceCneterLeftLeft + centerSpaceWidth, yEdge - chamferLength], [xSpaceCneterRightLeft, yEdge - chamferLength]], layer="Dwgs.User", width=wCut)) f.append(PolygoneLine(polygone=[[xSpaceCneterRightLeft + centerSpaceWidth, yEdge - chamferLength], [xSpaceRightLeft, yEdge - chamferLength]], layer="Dwgs.User", width=wCut)) f.append(Text(type="user", text=chamferComment, at=[xCenter, yEdge + sFabRef[0]], layer="Cmts.User", size=sFabRef, thickness=t2)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") ================================================ FILE: scripts/Connector/Connector_PhoenixContact/config_phoenix_KLCv1.0.yaml ================================================ # This holds the configuration information # using this config file will create KLCv2.x compatible footprints. lib_name_format_str: "Connectors_Phoenix" #lib_name_format_str: "Conn_Phoenix_{series:s}-{style:%s}_{pitch:.2f}" manufacturer: "PhoenixContact" #fp_name_format_string: '{man:s}_{series:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' fp_name_format_string: '{man:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' #mpn_format_string: '{subseries:s}_{rating:s}_{num_pins:s}-{style:s}{pitch:s}' mpn_format_string: '{subseries:s}-{style:s}' mpn_format_string_description: '{subseries:s}_{rating:s}/{num_pins:d}-{style:s}{pitch:s}' 3d_model_prefix: '${KISYS3DMOD}/' #keywords_format_string: 'phoenix_contact connector {mpn:s}{param_name:s}{order_info:s}' keywords_format_string: 'phoenix_contact connector {param_name:s}' orientation_str: ['Vertical', 'Angled'] flanged_str: ['', '_ThreadedFlange'] mount_hole_str: ['', '_MountHole'] pin_layers: ['*.Cu', '*.Mask'] #, '*.Paste' through hole: no paste! mount_hole_layers: ['*.Cu', '*.Mask'] with_fab_layer : False inner_details_on_fab : False courtyard_for_mountscrews : True ================================================ FILE: scripts/Connector/Connector_PhoenixContact/config_phoenix_KLCv1.1.yaml ================================================ # This holds the configuration information # using this config file will create KLCv2.x compatible footprints. lib_name_format_str: "Connectors_Phoenix" #lib_name_format_str: "Conn_Phoenix_{series:s}-{style:%s}_{pitch:.2f}" manufacturer: "PhoenixContact" #fp_name_format_string: '{man:s}_{series:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' fp_name_format_string: '{man:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' #mpn_format_string: '{subseries:s}_{rating:s}_{num_pins:s}-{style:s}{pitch:s}' mpn_format_string: '{subseries:s}-{style:s}' mpn_format_string_description: '{subseries:s}_{rating:s}/{num_pins:d}-{style:s}{pitch:s}' 3d_model_prefix: '${KISYS3DMOD}/' #keywords_format_string: 'phoenix_contact connector {mpn:s}{param_name:s}{order_info:s}' keywords_format_string: 'phoenix_contact connector {param_name:s}' orientation_str: ['Vertical', 'Angled'] flanged_str: ['', '_ThreadedFlange'] mount_hole_str: ['', '_MountHole'] pin_layers: ['*.Cu', '*.Mask'] #, '*.Paste' through hole: no paste! mount_hole_layers: ['*.Cu', '*.Mask'] with_fab_layer : True inner_details_on_fab : False courtyard_for_mountscrews : True ================================================ FILE: scripts/Connector/Connector_PhoenixContact/config_phoenix_KLCv2.0.yaml ================================================ # This holds the configuration information # using this config file will create KLCv2.x compatible footprints. lib_name_format_str: "Connectors_Phoenix" #lib_name_format_str: "Conn_Phoenix_{series:s}-{style:%s}_{pitch:.2f}" manufacturer: "PhoenixContact" #fp_name_format_string: '{man:s}_{series:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' fp_name_format_string: '{man:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' #mpn_format_string: '{subseries:s}_{rating:s}_{num_pins:s}-{style:s}{pitch:s}' mpn_format_string: '{subseries:s}-{style:s}' mpn_format_string_description: '{subseries:s}_{rating:s}/{num_pins:d}-{style:s}{pitch:s}' 3d_model_prefix: '${KISYS3DMOD}/' #keywords_format_string: 'phoenix_contact connector {mpn:s}{param_name:s}{order_info:s}' keywords_format_string: 'phoenix_contact connector {param_name:s}' orientation_str: ['Vertical', 'Angled'] flanged_str: ['', '_ThreadedFlange'] mount_hole_str: ['', '_MountHole'] pin_layers: ['*.Cu', '*.Mask'] #, '*.Paste' through hole: no paste! mount_hole_layers: ['*.Cu', '*.Mask'] with_fab_layer : True inner_details_on_fab : False courtyard_for_mountscrews : True ================================================ FILE: scripts/Connector/Connector_PhoenixContact/config_phoenix_KLCv3.0.yaml ================================================ # This holds the configuration information # using this config file will create KLCv2.x compatible footprints. #lib_name_format_str: "Conn_Phoenix_{series:s}-{style:%s}_{pitch:.2f}" lib_name_format_str: "Connector_Phoenix_{series:s}{suffix:s}" manufacturer: "PhoenixContact" #fp_name_format_string: '{man:s}_{series:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' fp_name_format_string: '{man:s}_{mpn:s}_{num_rows:d}x{num_pins:02d}_P{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' mpn_format_string: '{subseries:s}_{rating:s}_{num_pins:d}-{style:s}{pitch:s}' mpn_format_string_description: '{subseries:s}_{rating:s}/{num_pins:d}-{style:s}{pitch:s}' #mpn_format_string: '{subseries:s}-{style:s}' 3d_model_prefix: '${KISYS3DMOD}/' #keywords_format_string: 'phoenix_contact connector {mpn:s}{param_name:s}{order_info:s}' keywords_format_string: 'phoenix_contact connector {param_name:s}' orientation_str: ['Vertical', 'Horizontal'] flanged_str: ['', '_ThreadedFlange'] mount_hole_str: ['', '_MountHole'] pin_layers: ['*.Cu', '*.Mask'] #, '*.Paste' through hole: no paste! mount_hole_layers: ['*.Cu', '*.Mask'] with_fab_layer : True inner_details_on_fab : False courtyard_for_mountscrews : True ================================================ FILE: scripts/Connector/Connector_PhoenixContact/config_phoenix_TERA.yaml ================================================ # This holds the configuration information # using this config file will create KLCv2.x compatible footprints. lib_name_format_str: "Tera_Connectors_Phoenix" #lib_name_format_str: "Conn_Phoenix_{series:s}-{style:%s}_{pitch:.2f}" manufacturer: "PhoenixContact" #fp_name_format_string: '{man:s}_{series:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' fp_name_format_string: '{man:s}_{mpn:s}_{num_pins:02d}x{pitch:.2f}mm_{orientation:s}{flanged:s}{mount_hole:s}' #mpn_format_string: '{subseries:s}_{rating:s}_{num_pins:s}-{style:s}{pitch:s}' mpn_format_string: '{subseries:s}-{style:s}' mpn_format_string_description: '{subseries:s}_{rating:s}/{num_pins:d}-{style:s}{pitch:s}' 3d_model_prefix: '${TERA3DMOD}/' #keywords_format_string: 'phoenix_contact connector {mpn:s}{param_name:s}{order_info:s}' keywords_format_string: 'phoenix_contact connector {param_name:s}' orientation_str: ['Vertical', 'Angled'] flanged_str: ['', '_ThreadedFlange'] mount_hole_str: ['', '_MountHole'] pin_layers: ['*.Cu', '*.Mask'] #, '*.Paste' through hole: no paste! mount_hole_layers: ['*.Cu', '*.Mask'] with_fab_layer : True inner_details_on_fab : False courtyard_for_mountscrews : True ================================================ FILE: scripts/Connector/Connector_PhoenixContact/helpers.py ================================================ def round_to(value, base): return round(value/base) * base def v_add(p1,p2): return [p1[0]+p2[0],p1[1]+p2[1]] def round_crty_point(point, grid_size): return [round_to(point[0], grid_size),round_to(point[1], grid_size)] def offset_dir(coordinate, offset, center=0): if coordinate > center: return coordinate + offset elif coordinate< center: return coordinate - offset else: return coordinate def v_offset(point, offset, center = (0,0)): if type(center) is dict: center_x = float(center.get('x', 0.)) center_y = float(center.get('y', 0.)) else: center_x=center[0] center_y=center[1] if type(point) is dict: result={} result['x']=offset_dir(float(point.get('x', 0.)), offset, center_x) result['y']=offset_dir(float(point.get('y', 0.)), offset, center_y) return result return [ point[0] + (offset if point[0] >=center_x else -offset), point[1] + (offset if point[1] >=center_y else -offset) ] def offset_polyline(polyline_points, offset, center=(0,0)): resulting_points = [] for point in polyline_points: resulting_points.append(v_offset(point,offset,center)) return resulting_points def create_pin1_marker_triangle(bottom_y, center_x = 0, dimensions = [0.6,0.6], with_top_line = True): marker_width = dimensions[0] marker_height = dimensions[1] marker_top=bottom_y-marker_height marker_poly=[ {'x':center_x+marker_width/2, 'y':marker_top}, {'x':center_x, 'y':bottom_y}, {'x':center_x-marker_width/2, 'y':marker_top} ] if with_top_line: marker_poly.append({'x':center_x+marker_width/2, 'y':marker_top}) return marker_poly def create_pin1_marker_corner(top_y, left_x, sidelength = [1,1]): marker_poly=[ {'x':left_x, 'y':top_y + sidelength[1]}, {'x':left_x, 'y':top_y}, {'x':left_x + sidelength[0], 'y':top_y} ] return marker_poly ================================================ FILE: scripts/Connector/Connector_PhoenixContact/mc.py ================================================ #!/usr/bin/env python3 import sys import os from helpers import * import re import fnmatch import argparse import yaml #sys.path.append(os.path.join(sys.path[0],"..","..")) # load KicadModTree path #add KicadModTree to searchpath using export PYTHONPATH="${PYTHONPATH}/kicad-footprint-generator/" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from mc_params import seriesParams, dimensions, generate_description, all_params series = ['MC', '1,5'] def generate_one_footprint(motel, params, configuration): # Through-hole type shrouded header, Top entry type subseries, connector_style = params.series_name.split('-') pitch_mpn = '-{:g}'.format(params.pin_pitch) suffix = '_HighVoltage' if params.pin_pitch >= 5.08 else '' lib_name = configuration['lib_name_format_str'].format(series=series[0], style=series[1], pitch=params.pin_pitch, suffix=suffix) mpn = configuration['mpn_format_string'].format(subseries=subseries, style = connector_style, rating=series[1], num_pins=params.num_pins, pitch=pitch_mpn) footprint_name = configuration['fp_name_format_string'].format(man = configuration['manufacturer'], series = series[0], mpn = mpn, num_rows = 1, num_pins = params.num_pins, mounting_pad = "", pitch = params.pin_pitch, orientation = configuration['orientation_str'][1] if params.angled else configuration['orientation_str'][0], flanged = configuration['flanged_str'][1] if params.flanged else configuration['flanged_str'][0], mount_hole = configuration['mount_hole_str'][1] if params.mount_hole else configuration['mount_hole_str'][0]) calc_dim = dimensions(params) body_top_left=[calc_dim.left_to_pin,params.back_to_pin] body_bottom_right=v_add(body_top_left,[calc_dim.length,calc_dim.width]) silk_top_left=v_offset(body_top_left, configuration['silk_fab_offset']) silk_bottom_right=v_offset(body_bottom_right, configuration['silk_fab_offset']) center_x = (params.num_pins-1)/2.0*params.pin_pitch kicad_mod = Footprint(footprint_name) body_edge={ 'left': body_top_left[0], 'top': body_top_left[1], 'right': body_bottom_right[0], 'bottom': body_bottom_right[1], } mpn = configuration['mpn_format_string_description'].format(subseries=subseries, style = connector_style, rating=series[1], num_pins=params.num_pins, pitch=pitch_mpn) kicad_mod.setDescription(generate_description(params, mpn)) kicad_mod.setTags(configuration['keywords_format_string'].format(mpn=mpn, param_name=model, order_info = ', '.join(params.order_info))) #add the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=params.pin_pitch, pincount=params.num_pins, size=[params.pin_Sx, params.pin_Sy], drill=seriesParams.drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=configuration['pin_layers'], **optional_pad_params)) if params.mount_hole: kicad_mod.append(Pad(number='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=calc_dim.mount_hole_left, size=[seriesParams.mount_drill, seriesParams.mount_drill], \ drill=seriesParams.mount_drill, layers=configuration['mount_hole_layers'])) kicad_mod.append(Pad(number='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=calc_dim.mount_hole_right, size=[seriesParams.mount_drill, seriesParams.mount_drill], \ drill=seriesParams.mount_drill, layers=configuration['mount_hole_layers'])) #add an outline around the pins # create silscreen if params.angled: #kicad_mod.append(RectLine(start=silk_top_left, end=silk_bottom_right, layer='F.SilkS')) silkGab = params.pin_Sx/2.0+seriesParams.silk_pad_clearance kicad_mod.append(Line(start=silk_top_left, end=[silk_top_left[0], silk_bottom_right[1]], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_top_left[0], silk_bottom_right[1]], end=silk_bottom_right, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=silk_bottom_right, end=[silk_bottom_right[0], silk_top_left[1]], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=silk_top_left, end=[-silkGab, silk_top_left[1]], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_bottom_right[0], silk_top_left[1]], end=[(params.num_pins-1)*params.pin_pitch+silkGab, silk_top_left[1]],\ layer='F.SilkS', width=configuration['silk_line_width'])) for p in range(params.num_pins-1): kicad_mod.append(Line(start=[p*params.pin_pitch+silkGab, silk_top_left[1]], \ end=[(p+1)*params.pin_pitch-silkGab, silk_top_left[1]], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(RectLine(start=body_top_left, end=body_bottom_right, layer='F.Fab', width=configuration['fab_line_width'])) left = silk_top_left[0] + (seriesParams.flange_lenght if params.flanged else 0) right = silk_bottom_right[0] - (seriesParams.flange_lenght if params.flanged else 0) scoreline_y = seriesParams.scoreline_from_back+params.back_to_pin kicad_mod.append(Line(start=[left, scoreline_y], end=[right, scoreline_y], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(Line(start=[left +(0 if params.flanged else configuration['silk_fab_offset']), scoreline_y], end=[right-(0 if params.flanged else configuration['silk_fab_offset']), scoreline_y], layer='F.Fab', width=configuration['fab_line_width'])) if params.flanged: kicad_mod.append(Line(start=[left, silk_top_left[1]], end=[left, silk_bottom_right[1]], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[right, silk_top_left[1]], end=[right, silk_bottom_right[1]], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(Line(start=[left, body_top_left[1]], end=[left, body_bottom_right[1]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[right, body_top_left[1]], end=[right, body_bottom_right[1]], layer='F.Fab', width=configuration['fab_line_width'])) else: if not params.flanged: kicad_mod.append(RectLine(start=silk_top_left, end=silk_bottom_right, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(RectLine(start=body_top_left, end=body_bottom_right, layer='F.Fab', width=configuration['fab_line_width'])) else: flange_cutout = calc_dim.width-calc_dim.flange_width outline_poly=[ {'x':silk_top_left[0], 'y':silk_bottom_right[1]}, {'x':silk_bottom_right[0], 'y':silk_bottom_right[1]}, {'x':silk_bottom_right[0], 'y':silk_top_left[1]+flange_cutout}, {'x':silk_bottom_right[0]-seriesParams.flange_lenght, 'y':silk_top_left[1]+flange_cutout}, {'x':silk_bottom_right[0]-seriesParams.flange_lenght, 'y':silk_top_left[1]}, {'x':silk_top_left[0]+seriesParams.flange_lenght, 'y':silk_top_left[1]}, {'x':silk_top_left[0]+seriesParams.flange_lenght, 'y':silk_top_left[1]+flange_cutout}, {'x':silk_top_left[0], 'y':silk_top_left[1]+flange_cutout}, {'x':silk_top_left[0], 'y':silk_bottom_right[1]} ] kicad_mod.append(PolygoneLine(polygone=outline_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: outline_poly=offset_polyline(outline_poly,-configuration['silk_fab_offset'],(center_x,0)) kicad_mod.append(PolygoneLine(polygone=outline_poly, layer="F.Fab", width=configuration['fab_line_width'])) if params.flanged: kicad_mod.append(Circle(center=calc_dim.mount_hole_left, radius=1.9, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_right, radius=1.9, layer='F.SilkS', width=configuration['silk_line_width'])) if not params.mount_hole: kicad_mod.append(Circle(center=calc_dim.mount_hole_left, radius=1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_right, radius=1, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(Circle(center=calc_dim.mount_hole_left, radius=1.9, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_right, radius=1.9, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_left, radius=1, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_right, radius=1, layer='F.Fab', width=configuration['fab_line_width'])) for i in range(params.num_pins): plug_outline_translation = Translation(i*params.pin_pitch, 0) plug_outline_poly=[ {'x':-seriesParams.plug_arc_len/2.0, 'y':calc_dim.plug_front}, {'x':-seriesParams.plug_cut_len/2.0, 'y':calc_dim.plug_front}, {'x':-seriesParams.plug_cut_len/2.0, 'y':calc_dim.plug_front-seriesParams.plug_cut_width}, {'x':-seriesParams.plug_seperator_distance/2.0, 'y':calc_dim.plug_front-seriesParams.plug_cut_width}, {'x':-seriesParams.plug_seperator_distance/2.0, 'y':calc_dim.plug_back+seriesParams.plug_trapezoid_width}, {'x':-seriesParams.plug_trapezoid_short/2.0, 'y':calc_dim.plug_back+seriesParams.plug_trapezoid_width}, {'x':-seriesParams.plug_trapezoid_long/2.0, 'y':calc_dim.plug_back}, {'x':seriesParams.plug_trapezoid_long/2.0, 'y':calc_dim.plug_back}, {'x':seriesParams.plug_trapezoid_short/2.0, 'y':calc_dim.plug_back+seriesParams.plug_trapezoid_width}, {'x':seriesParams.plug_seperator_distance/2.0, 'y':calc_dim.plug_back+seriesParams.plug_trapezoid_width}, {'x':seriesParams.plug_seperator_distance/2.0, 'y':calc_dim.plug_front-seriesParams.plug_cut_width}, {'x':seriesParams.plug_cut_len/2.0, 'y':calc_dim.plug_front-seriesParams.plug_cut_width}, {'x':seriesParams.plug_cut_len/2.0, 'y':calc_dim.plug_front}, {'x':seriesParams.plug_arc_len/2.0, 'y':calc_dim.plug_front} ] plug_outline_translation.append(PolygoneLine(polygone=plug_outline_poly, layer='F.SilkS', width=configuration['silk_line_width'])) plug_outline_translation.append(Arc(start=[-seriesParams.plug_arc_len/2.0,calc_dim.plug_front], center=[0,calc_dim.plug_front+1.7], angle=47.6, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: plug_outline_translation.append(PolygoneLine(polygone=plug_outline_poly, layer="F.Fab", width=configuration['fab_line_width'])) plug_outline_translation.append(Arc(start=[-seriesParams.plug_arc_len/2.0,calc_dim.plug_front], center=[0,calc_dim.plug_front+1.7], angle=47.6, layer="F.Fab", width=configuration['fab_line_width'])) kicad_mod.append(plug_outline_translation) if params.mount_hole: kicad_mod.append(Circle(center=calc_dim.mount_hole_left, radius=seriesParams.mount_screw_head_r+configuration['silk_fab_offset'], layer='B.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_right, radius=seriesParams.mount_screw_head_r+configuration['silk_fab_offset'], layer='B.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_right, radius=seriesParams.mount_screw_head_r, layer='B.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_left, radius=seriesParams.mount_screw_head_r, layer='B.Fab', width=configuration['fab_line_width'])) ################################################## Courtyard ################################################## if params.angled: crtyd_top_left=v_offset([silk_top_left[0],-params.pin_Sy/2], configuration['courtyard_offset']['connector']) else: crtyd_top_left=v_offset(body_top_left, configuration['courtyard_offset']['connector']) crtyd_bottom_right=v_offset(body_bottom_right, configuration['courtyard_offset']['connector']) kicad_mod.append(RectLine(start=round_crty_point(crtyd_top_left, configuration['courtyard_grid']), end=round_crty_point(crtyd_bottom_right, configuration['courtyard_grid']), layer='F.CrtYd', width=configuration['courtyard_line_width'])) if params.mount_hole and configuration['courtyard_for_mountscrews']: kicad_mod.append(Circle(center=calc_dim.mount_hole_right, radius=seriesParams.mount_screw_head_r+configuration['courtyard_offset']['connector'], layer='B.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Circle(center=calc_dim.mount_hole_left, radius=seriesParams.mount_screw_head_r+configuration['courtyard_offset']['connector'], layer='B.CrtYd', width=configuration['courtyard_line_width'])) ################################################# Text Fields ################################################# addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':crtyd_top_left[1], 'bottom':crtyd_bottom_right[1]}, fp_name=footprint_name, text_y_inside_position='top') ################################################# Pin 1 Marker ################################################# if not params.angled: pin1_marker_poly = create_pin1_marker_corner(crtyd_top_left[1], body_top_left[0] - configuration['courtyard_offset']['connector'] + (seriesParams.flange_lenght if params.flanged else 0), [2,1.25]) kicad_mod.append(PolygoneLine(polygone=pin1_marker_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(PolygoneLine(polygone=pin1_marker_poly, layer='F.Fab', width=configuration['fab_line_width'])) else: kicad_mod.append(PolygoneLine(polygone=create_pin1_marker_triangle(-params.pin_Sy/2-0.2), layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(PolygoneLine( polygone=create_pin1_marker_triangle(bottom_y = 0, dimensions = [params.pin_Sx - 0.2, -body_top_left[1]], with_top_line = False), layer='F.Fab', width=configuration['fab_line_width'])) #################################################### 3d file ################################################### p3dname = '{prefix:s}{lib_name:s}.3dshapes/{fp_name}.wrl'.format(prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/'), lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=p3dname, at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) file_handler = KicadFileHandler(kicad_mod) out_dir = '{:s}.pretty/'.format(lib_name) if not os.path.exists(out_dir): os.makedirs(out_dir) file_handler.writeFile('{:s}.pretty/{:s}.kicad_mod'.format(lib_name, footprint_name)) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='config_phoenix_KLCv3.0.yaml') parser.add_argument('--model_filter', type=str, nargs='?', help='define a filter for what should be generated.', default="*") parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible model_filter_regobj=re.compile(fnmatch.translate(args.model_filter)) for model, params in all_params.items(): if model_filter_regobj.match(model): generate_one_footprint(model, params, configuration) ================================================ FILE: scripts/Connector/Connector_PhoenixContact/mc_params.py ================================================ from collections import namedtuple from collections import OrderedDict class seriesParams(): drill = 1.2 annular_ring = 0.3 # overwritten by minimum pad to pad clearance. mount_drill = 2.4 mount_screw_head_r = 2.1 flange_lenght = 4.8 scoreline_from_back = 6.0 plug_cut_len = 3.0 plug_cut_width = 4.3 plug_arc_len = 1.5 plug_trapezoid_short = 2.5 plug_trapezoid_long = 3.0 plug_trapezoid_width = 1 plug_seperator_distance = 1.5 silk_pad_clearance = 0.15 mount_screw_info = "ISO 1481-ST 2.2x4.5 C or ISO 7049-ST 2.2x4.5 C (http://www.fasteners.eu/standards/ISO/7049/)" # Connector voltage ratings: # Rated voltage (III/3) 160 V # Rated voltage (III/2) 160 V # Rated voltage (II/2) 250 V # Rated surge voltage (III/3) 2.5 kV # Rated surge voltage (III/2) 2.5 kV # Rated surge voltage (II/2) 2.5 kV # VDE 0110-1/4.97 2.5kV -> 1.5mm clearance min_pad_to_pad_clearance = 1.5 # Connector voltage ratings: # Rated voltage (III/3) 250 V # Rated voltage (III/2) 320 V # Rated voltage (II/2) 400 V # Rated surge voltage (III/3) 4 kV # Rated surge voltage (III/2) 4 kV # Rated surge voltage (II/2) 4 kV # VDE 0110-1/4.97 4kV -> 3mm clearance HV_min_pad_to_pad_clearance = 3.0 Params = namedtuple("Params",[ 'series_name', 'angled', 'flanged', 'num_pins', 'pin_pitch', 'mount_hole', 'order_info', 'mount_hole_to_pin', 'side_to_pin', 'back_to_pin', 'pin_Sx', 'pin_Sy' ]) def generate_params(num_pins, series_name, pin_pitch, angled, flanged, order_info, mount_hole=False, mount_hole_to_pin=None, side_to_pin=None, back_to_pin=None, min_pad_to_pad_clearance=seriesParams.min_pad_to_pad_clearance): nominal_pin_Sx = seriesParams.drill + 2 * seriesParams.annular_ring nominal_pin_Sy = seriesParams.drill + 2 * 1.2 return Params( series_name=series_name, angled=angled, flanged=flanged, num_pins=num_pins, pin_pitch=pin_pitch, mount_hole=mount_hole, order_info=order_info, mount_hole_to_pin=pin_pitch if mount_hole_to_pin is None else mount_hole_to_pin, side_to_pin=(3*pin_pitch if flanged else pin_pitch+2)/2.0 if side_to_pin is None else side_to_pin, back_to_pin= (8-9.2 if angled else 3-7.25) if back_to_pin is None else back_to_pin, pin_Sx=(nominal_pin_Sx if pin_pitch-nominal_pin_Sx >= min_pad_to_pad_clearance else pin_pitch - min_pad_to_pad_clearance), pin_Sy = nominal_pin_Sy ) all_params = { ################################################################################################################## # Pin Pitch 3.50mm ################################################################################################################## 'MC_01x02_G_3.5mm' : generate_params( 2, "MC-G", 3.5, True, False, OrderedDict([('1844210', '8A 160V')]), side_to_pin=2.45), 'MC_01x03_G_3.5mm' : generate_params( 3, "MC-G", 3.5, True, False, OrderedDict([('1844223', '8A 160V')]), side_to_pin=2.45), 'MC_01x04_G_3.5mm' : generate_params( 4, "MC-G", 3.5, True, False, OrderedDict([('1844236', '8A 160V')]), side_to_pin=2.45), 'MC_01x05_G_3.5mm' : generate_params( 5, "MC-G", 3.5, True, False, OrderedDict([('1844249', '8A 160V')]), side_to_pin=2.45), 'MC_01x06_G_3.5mm' : generate_params( 6, "MC-G", 3.5, True, False, OrderedDict([('1844252', '8A 160V')]), side_to_pin=2.45), 'MC_01x07_G_3.5mm' : generate_params( 7, "MC-G", 3.5, True, False, OrderedDict([('1844265', '8A 160V')]), side_to_pin=2.45), 'MC_01x08_G_3.5mm' : generate_params( 8, "MC-G", 3.5, True, False, OrderedDict([('1844278', '8A 160V')]), side_to_pin=2.45), 'MC_01x09_G_3.5mm' : generate_params( 9, "MC-G", 3.5, True, False, OrderedDict([('1844281', '8A 160V')]), side_to_pin=2.45), 'MC_01x10_G_3.5mm' : generate_params(10, "MC-G", 3.5, True, False, OrderedDict([('1844294', '8A 160V')]), side_to_pin=2.45), 'MC_01x11_G_3.5mm' : generate_params(11, "MC-G", 3.5, True, False, OrderedDict([('1844304', '8A 160V')]), side_to_pin=2.45), 'MC_01x12_G_3.5mm' : generate_params(12, "MC-G", 3.5, True, False, OrderedDict([('1844317', '8A 160V')]), side_to_pin=2.45), 'MC_01x13_G_3.5mm' : generate_params(13, "MC-G", 3.5, True, False, OrderedDict([('1844320', '8A 160V')]), side_to_pin=2.45), 'MC_01x14_G_3.5mm' : generate_params(14, "MC-G", 3.5, True, False, OrderedDict([('1844333', '8A 160V')]), side_to_pin=2.45), 'MC_01x15_G_3.5mm' : generate_params(15, "MC-G", 3.5, True, False, OrderedDict([('1844346', '8A 160V')]), side_to_pin=2.45), 'MC_01x16_G_3.5mm' : generate_params(16, "MC-G", 3.5, True, False, OrderedDict([('1844359', '8A 160V')]), side_to_pin=2.45), ################################################################################################################### 'MC_01x02_GF_3.5mm' : generate_params( 2, "MC-GF", 3.5, True, True, OrderedDict([('1843790', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x03_GF_3.5mm' : generate_params( 3, "MC-GF", 3.5, True, True, OrderedDict([('1843800', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x04_GF_3.5mm' : generate_params( 4, "MC-GF", 3.5, True, True, OrderedDict([('1843813', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x05_GF_3.5mm' : generate_params( 5, "MC-GF", 3.5, True, True, OrderedDict([('1843826', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x06_GF_3.5mm' : generate_params( 6, "MC-GF", 3.5, True, True, OrderedDict([('1843839', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x07_GF_3.5mm' : generate_params( 7, "MC-GF", 3.5, True, True, OrderedDict([('1843842', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x08_GF_3.5mm' : generate_params( 8, "MC-GF", 3.5, True, True, OrderedDict([('1843855', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x09_GF_3.5mm' : generate_params( 9, "MC-GF", 3.5, True, True, OrderedDict([('1843868', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x10_GF_3.5mm' : generate_params(10, "MC-GF", 3.5, True, True, OrderedDict([('1843871', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x11_GF_3.5mm' : generate_params(11, "MC-GF", 3.5, True, True, OrderedDict([('1843884', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x12_GF_3.5mm' : generate_params(12, "MC-GF", 3.5, True, True, OrderedDict([('1843897', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x13_GF_3.5mm' : generate_params(13, "MC-GF", 3.5, True, True, OrderedDict([('1843907', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x14_GF_3.5mm' : generate_params(14, "MC-GF", 3.5, True, True, OrderedDict([('1843910', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x15_GF_3.5mm' : generate_params(15, "MC-GF", 3.5, True, True, OrderedDict([('1843923', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MC_01x16_GF_3.5mm' : generate_params(16, "MC-GF", 3.5, True, True, OrderedDict([('1843936', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), ################################################################################################################### 'MC_01x02_GF_3.5mm_MH' : generate_params( 2, "MC-GF", 3.5, True, True, OrderedDict([('1843790', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x03_GF_3.5mm_MH' : generate_params( 3, "MC-GF", 3.5, True, True, OrderedDict([('1843800', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x04_GF_3.5mm_MH' : generate_params( 4, "MC-GF", 3.5, True, True, OrderedDict([('1843813', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x05_GF_3.5mm_MH' : generate_params( 5, "MC-GF", 3.5, True, True, OrderedDict([('1843826', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x06_GF_3.5mm_MH' : generate_params( 6, "MC-GF", 3.5, True, True, OrderedDict([('1843839', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x07_GF_3.5mm_MH' : generate_params( 7, "MC-GF", 3.5, True, True, OrderedDict([('1843842', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x08_GF_3.5mm_MH' : generate_params( 8, "MC-GF", 3.5, True, True, OrderedDict([('1843855', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x09_GF_3.5mm_MH' : generate_params( 9, "MC-GF", 3.5, True, True, OrderedDict([('1843868', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x10_GF_3.5mm_MH' : generate_params(10, "MC-GF", 3.5, True, True, OrderedDict([('1843871', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x11_GF_3.5mm_MH' : generate_params(11, "MC-GF", 3.5, True, True, OrderedDict([('1843884', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x12_GF_3.5mm_MH' : generate_params(12, "MC-GF", 3.5, True, True, OrderedDict([('1843897', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x13_GF_3.5mm_MH' : generate_params(13, "MC-GF", 3.5, True, True, OrderedDict([('1843907', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x14_GF_3.5mm_MH' : generate_params(14, "MC-GF", 3.5, True, True, OrderedDict([('1843910', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x15_GF_3.5mm_MH' : generate_params(15, "MC-GF", 3.5, True, True, OrderedDict([('1843923', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MC_01x16_GF_3.5mm_MH' : generate_params(16, "MC-GF", 3.5, True, True, OrderedDict([('1843936', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), ################################################################################################################### 'MCV_01x02_G_3.5mm' : generate_params( 2, "MCV-G", 3.5, False, False, OrderedDict([('1843606', '8A 160V')]), side_to_pin=2.45), 'MCV_01x03_G_3.5mm' : generate_params( 3, "MCV-G", 3.5, False, False, OrderedDict([('1843619', '8A 160V')]), side_to_pin=2.45), 'MCV_01x04_G_3.5mm' : generate_params( 4, "MCV-G", 3.5, False, False, OrderedDict([('1843622', '8A 160V')]), side_to_pin=2.45), 'MCV_01x05_G_3.5mm' : generate_params( 5, "MCV-G", 3.5, False, False, OrderedDict([('1843635', '8A 160V')]), side_to_pin=2.45), 'MCV_01x06_G_3.5mm' : generate_params( 6, "MCV-G", 3.5, False, False, OrderedDict([('1843648', '8A 160V')]), side_to_pin=2.45), 'MCV_01x07_G_3.5mm' : generate_params( 7, "MCV-G", 3.5, False, False, OrderedDict([('1843651', '8A 160V')]), side_to_pin=2.45), 'MCV_01x08_G_3.5mm' : generate_params( 8, "MCV-G", 3.5, False, False, OrderedDict([('1843664', '8A 160V')]), side_to_pin=2.45), 'MCV_01x09_G_3.5mm' : generate_params( 9, "MCV-G", 3.5, False, False, OrderedDict([('1843677', '8A 160V')]), side_to_pin=2.45), 'MCV_01x10_G_3.5mm' : generate_params(10, "MCV-G", 3.5, False, False, OrderedDict([('1843680', '8A 160V')]), side_to_pin=2.45), 'MCV_01x11_G_3.5mm' : generate_params(11, "MCV-G", 3.5, False, False, OrderedDict([('1843693', '8A 160V')]), side_to_pin=2.45), 'MCV_01x12_G_3.5mm' : generate_params(12, "MCV-G", 3.5, False, False, OrderedDict([('1843703', '8A 160V')]), side_to_pin=2.45), 'MCV_01x13_G_3.5mm' : generate_params(13, "MCV-G", 3.5, False, False, OrderedDict([('1843716', '8A 160V')]), side_to_pin=2.45), 'MCV_01x14_G_3.5mm' : generate_params(14, "MCV-G", 3.5, False, False, OrderedDict([('1843729', '8A 160V')]), side_to_pin=2.45), 'MCV_01x15_G_3.5mm' : generate_params(15, "MCV-G", 3.5, False, False, OrderedDict([('1843732', '8A 160V')]), side_to_pin=2.45), 'MCV_01x16_G_3.5mm' : generate_params(16, "MCV-G", 3.5, False, False, OrderedDict([('1843745', '8A 160V')]), side_to_pin=2.45), ################################################################################################################### 'MCV_01x02_GF_3.5mm' : generate_params( 2, "MCV-GF", 3.5, False, True, OrderedDict([('1843224', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x03_GF_3.5mm' : generate_params( 3, "MCV-GF", 3.5, False, True, OrderedDict([('1843237', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x04_GF_3.5mm' : generate_params( 4, "MCV-GF", 3.5, False, True, OrderedDict([('1843240', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x05_GF_3.5mm' : generate_params( 5, "MCV-GF", 3.5, False, True, OrderedDict([('1843253', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x06_GF_3.5mm' : generate_params( 6, "MCV-GF", 3.5, False, True, OrderedDict([('1843266', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x07_GF_3.5mm' : generate_params( 7, "MCV-GF", 3.5, False, True, OrderedDict([('1843279', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x08_GF_3.5mm' : generate_params( 8, "MCV-GF", 3.5, False, True, OrderedDict([('1843282', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x09_GF_3.5mm' : generate_params( 9, "MCV-GF", 3.5, False, True, OrderedDict([('1843295', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x10_GF_3.5mm' : generate_params(10, "MCV-GF", 3.5, False, True, OrderedDict([('1843305', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x11_GF_3.5mm' : generate_params(11, "MCV-GF", 3.5, False, True, OrderedDict([('1843318', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x12_GF_3.5mm' : generate_params(12, "MCV-GF", 3.5, False, True, OrderedDict([('1843321', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x13_GF_3.5mm' : generate_params(13, "MCV-GF", 3.5, False, True, OrderedDict([('1843334', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x14_GF_3.5mm' : generate_params(14, "MCV-GF", 3.5, False, True, OrderedDict([('1843347', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x15_GF_3.5mm' : generate_params(15, "MCV-GF", 3.5, False, True, OrderedDict([('1843350', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), 'MCV_01x16_GF_3.5mm' : generate_params(16, "MCV-GF", 3.5, False, True, OrderedDict([('1843363', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3), ################################################################################################################### 'MCV_01x02_GF_3.5mm_MH' : generate_params( 2, "MCV-GF", 3.5, False, True, OrderedDict([('1843224', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x03_GF_3.5mm_MH' : generate_params( 3, "MCV-GF", 3.5, False, True, OrderedDict([('1843237', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x04_GF_3.5mm_MH' : generate_params( 4, "MCV-GF", 3.5, False, True, OrderedDict([('1843240', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x05_GF_3.5mm_MH' : generate_params( 5, "MCV-GF", 3.5, False, True, OrderedDict([('1843253', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x06_GF_3.5mm_MH' : generate_params( 6, "MCV-GF", 3.5, False, True, OrderedDict([('1843266', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x07_GF_3.5mm_MH' : generate_params( 7, "MCV-GF", 3.5, False, True, OrderedDict([('1843279', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x08_GF_3.5mm_MH' : generate_params( 8, "MCV-GF", 3.5, False, True, OrderedDict([('1843282', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x09_GF_3.5mm_MH' : generate_params( 9, "MCV-GF", 3.5, False, True, OrderedDict([('1843295', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x10_GF_3.5mm_MH' : generate_params(10, "MCV-GF", 3.5, False, True, OrderedDict([('1843305', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x11_GF_3.5mm_MH' : generate_params(11, "MCV-GF", 3.5, False, True, OrderedDict([('1843318', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x12_GF_3.5mm_MH' : generate_params(12, "MCV-GF", 3.5, False, True, OrderedDict([('1843321', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x13_GF_3.5mm_MH' : generate_params(13, "MCV-GF", 3.5, False, True, OrderedDict([('1843334', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x14_GF_3.5mm_MH' : generate_params(14, "MCV-GF", 3.5, False, True, OrderedDict([('1843347', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x15_GF_3.5mm_MH' : generate_params(15, "MCV-GF", 3.5, False, True, OrderedDict([('1843350', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), 'MCV_01x16_GF_3.5mm_MH' : generate_params(16, "MCV-GF", 3.5, False, True, OrderedDict([('1843363', '8A 160V')]), side_to_pin=6.9, mount_hole_to_pin=4.3, mount_hole=True), ################################################################################################################## # Pin Pitch 3.81mm ################################################################################################################## 'MC_01x02_G_3.81mm' : generate_params( 2, "MC-G", 3.81, True, False, OrderedDict([('1803277', '8A 160V')]), side_to_pin=2.6), 'MC_01x03_G_3.81mm' : generate_params( 3, "MC-G", 3.81, True, False, OrderedDict([('1803280', '8A 160V')]), side_to_pin=2.6), 'MC_01x04_G_3.81mm' : generate_params( 4, "MC-G", 3.81, True, False, OrderedDict([('1803293', '8A 160V')]), side_to_pin=2.6), 'MC_01x05_G_3.81mm' : generate_params( 5, "MC-G", 3.81, True, False, OrderedDict([('1803303', '8A 160V')]), side_to_pin=2.6), 'MC_01x06_G_3.81mm' : generate_params( 6, "MC-G", 3.81, True, False, OrderedDict([('1803316', '8A 160V')]), side_to_pin=2.6), 'MC_01x07_G_3.81mm' : generate_params( 7, "MC-G", 3.81, True, False, OrderedDict([('1803329', '8A 160V')]), side_to_pin=2.6), 'MC_01x08_G_3.81mm' : generate_params( 8, "MC-G", 3.81, True, False, OrderedDict([('1803332', '8A 160V')]), side_to_pin=2.6), 'MC_01x09_G_3.81mm' : generate_params( 9, "MC-G", 3.81, True, False, OrderedDict([('1803345', '8A 160V')]), side_to_pin=2.6), 'MC_01x10_G_3.81mm' : generate_params(10, "MC-G", 3.81, True, False, OrderedDict([('1803358', '8A 160V')]), side_to_pin=2.6), 'MC_01x11_G_3.81mm' : generate_params(11, "MC-G", 3.81, True, False, OrderedDict([('1803361', '8A 160V')]), side_to_pin=2.6), 'MC_01x12_G_3.81mm' : generate_params(12, "MC-G", 3.81, True, False, OrderedDict([('1803374', '8A 160V')]), side_to_pin=2.6), 'MC_01x13_G_3.81mm' : generate_params(13, "MC-G", 3.81, True, False, OrderedDict([('1803387', '8A 160V')]), side_to_pin=2.6), 'MC_01x14_G_3.81mm' : generate_params(14, "MC-G", 3.81, True, False, OrderedDict([('1803390', '8A 160V')]), side_to_pin=2.6), 'MC_01x15_G_3.81mm' : generate_params(15, "MC-G", 3.81, True, False, OrderedDict([('1803400', '8A 160V')]), side_to_pin=2.6), 'MC_01x16_G_3.81mm' : generate_params(16, "MC-G", 3.81, True, False, OrderedDict([('1803413', '8A 160V')]), side_to_pin=2.6), ################################################################################################################### 'MC_01x02_GF_3.81mm' : generate_params( 2, "MC-GF", 3.81, True, True, OrderedDict([('1827868', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x03_GF_3.81mm' : generate_params( 3, "MC-GF", 3.81, True, True, OrderedDict([('1827871', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x04_GF_3.81mm' : generate_params( 4, "MC-GF", 3.81, True, True, OrderedDict([('1827884', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x05_GF_3.81mm' : generate_params( 5, "MC-GF", 3.81, True, True, OrderedDict([('1827897', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x06_GF_3.81mm' : generate_params( 6, "MC-GF", 3.81, True, True, OrderedDict([('1827907', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x07_GF_3.81mm' : generate_params( 7, "MC-GF", 3.81, True, True, OrderedDict([('1827910', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x08_GF_3.81mm' : generate_params( 8, "MC-GF", 3.81, True, True, OrderedDict([('1827923', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x09_GF_3.81mm' : generate_params( 9, "MC-GF", 3.81, True, True, OrderedDict([('1827936', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x10_GF_3.81mm' : generate_params(10, "MC-GF", 3.81, True, True, OrderedDict([('1827949', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x11_GF_3.81mm' : generate_params(11, "MC-GF", 3.81, True, True, OrderedDict([('1827952', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x12_GF_3.81mm' : generate_params(12, "MC-GF", 3.81, True, True, OrderedDict([('1827965', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x13_GF_3.81mm' : generate_params(13, "MC-GF", 3.81, True, True, OrderedDict([('1827978', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x14_GF_3.81mm' : generate_params(14, "MC-GF", 3.81, True, True, OrderedDict([('1827981', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x15_GF_3.81mm' : generate_params(15, "MC-GF", 3.81, True, True, OrderedDict([('1827994', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MC_01x16_GF_3.81mm' : generate_params(16, "MC-GF", 3.81, True, True, OrderedDict([('1828003', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), ################################################################################################################### 'MC_01x02_GF_3.81mm_MH' : generate_params( 2, "MC-GF", 3.81, True, True, OrderedDict([('1827868', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x03_GF_3.81mm_MH' : generate_params( 3, "MC-GF", 3.81, True, True, OrderedDict([('1827871', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x04_GF_3.81mm_MH' : generate_params( 4, "MC-GF", 3.81, True, True, OrderedDict([('1827884', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x05_GF_3.81mm_MH' : generate_params( 5, "MC-GF", 3.81, True, True, OrderedDict([('1827897', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x06_GF_3.81mm_MH' : generate_params( 6, "MC-GF", 3.81, True, True, OrderedDict([('1827907', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x07_GF_3.81mm_MH' : generate_params( 7, "MC-GF", 3.81, True, True, OrderedDict([('1827910', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x08_GF_3.81mm_MH' : generate_params( 8, "MC-GF", 3.81, True, True, OrderedDict([('1827923', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x09_GF_3.81mm_MH' : generate_params( 9, "MC-GF", 3.81, True, True, OrderedDict([('1827936', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x10_GF_3.81mm_MH' : generate_params(10, "MC-GF", 3.81, True, True, OrderedDict([('1827949', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x11_GF_3.81mm_MH' : generate_params(11, "MC-GF", 3.81, True, True, OrderedDict([('1827952', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x12_GF_3.81mm_MH' : generate_params(12, "MC-GF", 3.81, True, True, OrderedDict([('1827965', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x13_GF_3.81mm_MH' : generate_params(13, "MC-GF", 3.81, True, True, OrderedDict([('1827978', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x14_GF_3.81mm_MH' : generate_params(14, "MC-GF", 3.81, True, True, OrderedDict([('1827981', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x15_GF_3.81mm_MH' : generate_params(15, "MC-GF", 3.81, True, True, OrderedDict([('1827994', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MC_01x16_GF_3.81mm_MH' : generate_params(16, "MC-GF", 3.81, True, True, OrderedDict([('1828003', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), ################################################################################################################### 'MCV_01x02_G_3.81mm' : generate_params( 2, "MCV-G", 3.81, False, False, OrderedDict([('1803426', '8A 160V')]), side_to_pin=2.6), 'MCV_01x03_G_3.81mm' : generate_params( 3, "MCV-G", 3.81, False, False, OrderedDict([('1803439', '8A 160V')]), side_to_pin=2.6), 'MCV_01x04_G_3.81mm' : generate_params( 4, "MCV-G", 3.81, False, False, OrderedDict([('1803442', '8A 160V')]), side_to_pin=2.6), 'MCV_01x05_G_3.81mm' : generate_params( 5, "MCV-G", 3.81, False, False, OrderedDict([('1803455', '8A 160V')]), side_to_pin=2.6), 'MCV_01x06_G_3.81mm' : generate_params( 6, "MCV-G", 3.81, False, False, OrderedDict([('1803468', '8A 160V')]), side_to_pin=2.6), 'MCV_01x07_G_3.81mm' : generate_params( 7, "MCV-G", 3.81, False, False, OrderedDict([('1803471', '8A 160V')]), side_to_pin=2.6), 'MCV_01x08_G_3.81mm' : generate_params( 8, "MCV-G", 3.81, False, False, OrderedDict([('1803484', '8A 160V')]), side_to_pin=2.6), 'MCV_01x09_G_3.81mm' : generate_params( 9, "MCV-G", 3.81, False, False, OrderedDict([('1803497', '8A 160V')]), side_to_pin=2.6), 'MCV_01x10_G_3.81mm' : generate_params(10, "MCV-G", 3.81, False, False, OrderedDict([('1803507', '8A 160V')]), side_to_pin=2.6), 'MCV_01x11_G_3.81mm' : generate_params(11, "MCV-G", 3.81, False, False, OrderedDict([('1803510', '8A 160V')]), side_to_pin=2.6), 'MCV_01x12_G_3.81mm' : generate_params(12, "MCV-G", 3.81, False, False, OrderedDict([('1803523', '8A 160V')]), side_to_pin=2.6), 'MCV_01x13_G_3.81mm' : generate_params(13, "MCV-G", 3.81, False, False, OrderedDict([('1803536', '8A 160V')]), side_to_pin=2.6), 'MCV_01x14_G_3.81mm' : generate_params(14, "MCV-G", 3.81, False, False, OrderedDict([('1803549', '8A 160V')]), side_to_pin=2.6), 'MCV_01x15_G_3.81mm' : generate_params(15, "MCV-G", 3.81, False, False, OrderedDict([('1803552', '8A 160V')]), side_to_pin=2.6), 'MCV_01x16_G_3.81mm' : generate_params(16, "MCV-G", 3.81, False, False, OrderedDict([('1803565', '8A 160V')]), side_to_pin=2.6), ################################################################################################################### 'MCV_01x02_GF_3.81mm' : generate_params( 2, "MCV-GF", 3.81, False, True, OrderedDict([('1830596', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x03_GF_3.81mm' : generate_params( 3, "MCV-GF", 3.81, False, True, OrderedDict([('1830606', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x04_GF_3.81mm' : generate_params( 4, "MCV-GF", 3.81, False, True, OrderedDict([('1830619', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x05_GF_3.81mm' : generate_params( 5, "MCV-GF", 3.81, False, True, OrderedDict([('1830622', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x06_GF_3.81mm' : generate_params( 6, "MCV-GF", 3.81, False, True, OrderedDict([('1830635', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x07_GF_3.81mm' : generate_params( 7, "MCV-GF", 3.81, False, True, OrderedDict([('1830648', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x08_GF_3.81mm' : generate_params( 8, "MCV-GF", 3.81, False, True, OrderedDict([('1830651', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x09_GF_3.81mm' : generate_params( 9, "MCV-GF", 3.81, False, True, OrderedDict([('1830664', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x10_GF_3.81mm' : generate_params(10, "MCV-GF", 3.81, False, True, OrderedDict([('1830677', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x11_GF_3.81mm' : generate_params(11, "MCV-GF", 3.81, False, True, OrderedDict([('1830680', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x12_GF_3.81mm' : generate_params(12, "MCV-GF", 3.81, False, True, OrderedDict([('1830693', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x13_GF_3.81mm' : generate_params(13, "MCV-GF", 3.81, False, True, OrderedDict([('1830703', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x14_GF_3.81mm' : generate_params(14, "MCV-GF", 3.81, False, True, OrderedDict([('1830716', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x15_GF_3.81mm' : generate_params(15, "MCV-GF", 3.81, False, True, OrderedDict([('1830729', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), 'MCV_01x16_GF_3.81mm' : generate_params(16, "MCV-GF", 3.81, False, True, OrderedDict([('1830732', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5), ################################################################################################################### 'MCV_01x02_GF_3.81mm_MH' : generate_params( 2, "MCV-GF", 3.81, False, True, OrderedDict([('1830596', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x03_GF_3.81mm_MH' : generate_params( 3, "MCV-GF", 3.81, False, True, OrderedDict([('1830606', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x04_GF_3.81mm_MH' : generate_params( 4, "MCV-GF", 3.81, False, True, OrderedDict([('1830619', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x05_GF_3.81mm_MH' : generate_params( 5, "MCV-GF", 3.81, False, True, OrderedDict([('1830622', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x06_GF_3.81mm_MH' : generate_params( 6, "MCV-GF", 3.81, False, True, OrderedDict([('1830635', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x07_GF_3.81mm_MH' : generate_params( 7, "MCV-GF", 3.81, False, True, OrderedDict([('1830648', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x08_GF_3.81mm_MH' : generate_params( 8, "MCV-GF", 3.81, False, True, OrderedDict([('1830651', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x09_GF_3.81mm_MH' : generate_params( 9, "MCV-GF", 3.81, False, True, OrderedDict([('1830664', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x10_GF_3.81mm_MH' : generate_params(10, "MCV-GF", 3.81, False, True, OrderedDict([('1830677', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x11_GF_3.81mm_MH' : generate_params(11, "MCV-GF", 3.81, False, True, OrderedDict([('1830680', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x12_GF_3.81mm_MH' : generate_params(12, "MCV-GF", 3.81, False, True, OrderedDict([('1830693', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x13_GF_3.81mm_MH' : generate_params(13, "MCV-GF", 3.81, False, True, OrderedDict([('1830703', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x14_GF_3.81mm_MH' : generate_params(14, "MCV-GF", 3.81, False, True, OrderedDict([('1830716', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x15_GF_3.81mm_MH' : generate_params(15, "MCV-GF", 3.81, False, True, OrderedDict([('1830729', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), 'MCV_01x16_GF_3.81mm_MH' : generate_params(16, "MCV-GF", 3.81, False, True, OrderedDict([('1830732', '8A 160V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True), ################################################################################################################## # Pin Pitch 5.08mm ################################################################################################################## 'MC_01x02_G_5.08mm' : generate_params( 2, "MC-G", 5.08, True, False, OrderedDict([('1836189', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x03_G_5.08mm' : generate_params( 3, "MC-G", 5.08, True, False, OrderedDict([('1836192', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x04_G_5.08mm' : generate_params( 4, "MC-G", 5.08, True, False, OrderedDict([('1836202', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x05_G_5.08mm' : generate_params( 5, "MC-G", 5.08, True, False, OrderedDict([('1836215', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x06_G_5.08mm' : generate_params( 6, "MC-G", 5.08, True, False, OrderedDict([('1836228', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x07_G_5.08mm' : generate_params( 7, "MC-G", 5.08, True, False, OrderedDict([('1836231', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x08_G_5.08mm' : generate_params( 8, "MC-G", 5.08, True, False, OrderedDict([('1836244', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x09_G_5.08mm' : generate_params( 9, "MC-G", 5.08, True, False, OrderedDict([('1836257', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x10_G_5.08mm' : generate_params(10, "MC-G", 5.08, True, False, OrderedDict([('1836260', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x11_G_5.08mm' : generate_params(11, "MC-G", 5.08, True, False, OrderedDict([('1836273', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x12_G_5.08mm' : generate_params(12, "MC-G", 5.08, True, False, OrderedDict([('1836286', '8A 320V')]), side_to_pin=2.54, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), ################################################################################################################### 'MC_01x02_GF_5.08mm' : generate_params( 2, "MC-GF", 5.08, True, True, OrderedDict([('1847466', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x03_GF_5.08mm' : generate_params( 3, "MC-GF", 5.08, True, True, OrderedDict([('1847479', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x04_GF_5.08mm' : generate_params( 4, "MC-GF", 5.08, True, True, OrderedDict([('1847482', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x05_GF_5.08mm' : generate_params( 5, "MC-GF", 5.08, True, True, OrderedDict([('1847495', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x06_GF_5.08mm' : generate_params( 6, "MC-GF", 5.08, True, True, OrderedDict([('1847505', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x07_GF_5.08mm' : generate_params( 7, "MC-GF", 5.08, True, True, OrderedDict([('1847518', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x08_GF_5.08mm' : generate_params( 8, "MC-GF", 5.08, True, True, OrderedDict([('1847521', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x09_GF_5.08mm' : generate_params( 9, "MC-GF", 5.08, True, True, OrderedDict([('1847534', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x10_GF_5.08mm' : generate_params(10, "MC-GF", 5.08, True, True, OrderedDict([('1847547', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x11_GF_5.08mm' : generate_params(11, "MC-GF", 5.08, True, True, OrderedDict([('1847550', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x12_GF_5.08mm' : generate_params(12, "MC-GF", 5.08, True, True, OrderedDict([('1847563', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), ################################################################################################################### 'MC_01x02_GF_5.08mm_MH' : generate_params( 2, "MC-GF", 5.08, True, True, OrderedDict([('1847466', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x03_GF_5.08mm_MH' : generate_params( 3, "MC-GF", 5.08, True, True, OrderedDict([('1847479', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x04_GF_5.08mm_MH' : generate_params( 4, "MC-GF", 5.08, True, True, OrderedDict([('1847482', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x05_GF_5.08mm_MH' : generate_params( 5, "MC-GF", 5.08, True, True, OrderedDict([('1847495', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x06_GF_5.08mm_MH' : generate_params( 6, "MC-GF", 5.08, True, True, OrderedDict([('1847505', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x07_GF_5.08mm_MH' : generate_params( 7, "MC-GF", 5.08, True, True, OrderedDict([('1847518', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x08_GF_5.08mm_MH' : generate_params( 8, "MC-GF", 5.08, True, True, OrderedDict([('1847521', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x09_GF_5.08mm_MH' : generate_params( 9, "MC-GF", 5.08, True, True, OrderedDict([('1847534', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x10_GF_5.08mm_MH' : generate_params(10, "MC-GF", 5.08, True, True, OrderedDict([('1847547', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x11_GF_5.08mm_MH' : generate_params(11, "MC-GF", 5.08, True, True, OrderedDict([('1847550', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MC_01x12_GF_5.08mm_MH' : generate_params(12, "MC-GF", 5.08, True, True, OrderedDict([('1847563', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), ################################################################################################################### 'MCV_01x02_G_5.08mm' : generate_params( 2, "MCV-G", 5.08, False, False, OrderedDict([('1836299', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x03_G_5.08mm' : generate_params( 3, "MCV-G", 5.08, False, False, OrderedDict([('1836309', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x04_G_5.08mm' : generate_params( 4, "MCV-G", 5.08, False, False, OrderedDict([('1836312', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x05_G_5.08mm' : generate_params( 5, "MCV-G", 5.08, False, False, OrderedDict([('1836325', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x06_G_5.08mm' : generate_params( 6, "MCV-G", 5.08, False, False, OrderedDict([('1836338', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x07_G_5.08mm' : generate_params( 7, "MCV-G", 5.08, False, False, OrderedDict([('1836341', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x08_G_5.08mm' : generate_params( 8, "MCV-G", 5.08, False, False, OrderedDict([('1836354', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x09_G_5.08mm' : generate_params( 9, "MCV-G", 5.08, False, False, OrderedDict([('1836367', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x10_G_5.08mm' : generate_params(10, "MCV-G", 5.08, False, False, OrderedDict([('1836370', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x11_G_5.08mm' : generate_params(11, "MCV-G", 5.08, False, False, OrderedDict([('1836383', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x12_G_5.08mm' : generate_params(12, "MCV-G", 5.08, False, False, OrderedDict([('1836396', '8A 320V')]), side_to_pin=2.54, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), ################################################################################################################### 'MCV_01x02_GF_5.08mm' : generate_params( 2, "MCV-GF", 5.08, False, True, OrderedDict([('1847615', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x03_GF_5.08mm' : generate_params( 3, "MCV-GF", 5.08, False, True, OrderedDict([('1847628', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x04_GF_5.08mm' : generate_params( 4, "MCV-GF", 5.08, False, True, OrderedDict([('1847631', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x05_GF_5.08mm' : generate_params( 5, "MCV-GF", 5.08, False, True, OrderedDict([('1847644', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x06_GF_5.08mm' : generate_params( 6, "MCV-GF", 5.08, False, True, OrderedDict([('1847657', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x07_GF_5.08mm' : generate_params( 7, "MCV-GF", 5.08, False, True, OrderedDict([('1847660', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x08_GF_5.08mm' : generate_params( 8, "MCV-GF", 5.08, False, True, OrderedDict([('1847673', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x09_GF_5.08mm' : generate_params( 9, "MCV-GF", 5.08, False, True, OrderedDict([('1847686', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x10_GF_5.08mm' : generate_params(10, "MCV-GF", 5.08, False, True, OrderedDict([('1847699', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x11_GF_5.08mm' : generate_params(11, "MCV-GF", 5.08, False, True, OrderedDict([('1847709', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x12_GF_5.08mm' : generate_params(12, "MCV-GF", 5.08, False, True, OrderedDict([('1847712', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), ################################################################################################################### 'MCV_01x02_GF_5.08mm_MH' : generate_params( 2, "MCV-GF", 5.08, False, True, OrderedDict([('1847615', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x03_GF_5.08mm_MH' : generate_params( 3, "MCV-GF", 5.08, False, True, OrderedDict([('1847628', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x04_GF_5.08mm_MH' : generate_params( 4, "MCV-GF", 5.08, False, True, OrderedDict([('1847631', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x05_GF_5.08mm_MH' : generate_params( 5, "MCV-GF", 5.08, False, True, OrderedDict([('1847644', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x06_GF_5.08mm_MH' : generate_params( 6, "MCV-GF", 5.08, False, True, OrderedDict([('1847657', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x07_GF_5.08mm_MH' : generate_params( 7, "MCV-GF", 5.08, False, True, OrderedDict([('1847660', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x08_GF_5.08mm_MH' : generate_params( 8, "MCV-GF", 5.08, False, True, OrderedDict([('1847673', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x09_GF_5.08mm_MH' : generate_params( 9, "MCV-GF", 5.08, False, True, OrderedDict([('1847686', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x10_GF_5.08mm_MH' : generate_params(10, "MCV-GF", 5.08, False, True, OrderedDict([('1847699', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x11_GF_5.08mm_MH' : generate_params(11, "MCV-GF", 5.08, False, True, OrderedDict([('1847709', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance), 'MCV_01x12_GF_5.08mm_MH' : generate_params(12, "MCV-GF", 5.08, False, True, OrderedDict([('1847712', '8A 320V')]), side_to_pin=7.1, mount_hole_to_pin=4.5, mount_hole=True, back_to_pin=2.9-7.25, min_pad_to_pad_clearance=seriesParams.HV_min_pad_to_pad_clearance) } #lock_cutout= CalcDim=namedtuple("CalcDim",[ "length", "width", "left_to_pin", "mount_hole_left", "mount_hole_right", "flange_width", "plug_front", "plug_back" ]) def dimensions(params): mount_hole_y = 0.9 if params.angled else 0.0 width = 9.2 if params.angled else 7.25 return CalcDim( length = (params.num_pins-1)*params.pin_pitch + 2*params.side_to_pin ,width = width ,left_to_pin = -params.side_to_pin ,mount_hole_left = [-params.mount_hole_to_pin,mount_hole_y] ,mount_hole_right = [(params.num_pins-1)*params.pin_pitch+params.mount_hole_to_pin,mount_hole_y] ,flange_width = 9.2 if params.angled else 6.0 ,plug_front = width + params.back_to_pin -0.75 ,plug_back = params.back_to_pin+0.6+0.25 ) def generate_description(params, mpn): d = "Generic Phoenix Contact connector footprint for: " + mpn + "; number of pins: " + ("%02d" %params.num_pins) + "; pin pitch: " + (('%.2f' % params.pin_pitch))\ +"mm" + ('; Angled' if params.angled else '; Vertical')\ + ('; threaded flange' + ('; footprint includes mount hole for mounting screw: ' + seriesParams.mount_screw_info if params.mount_hole else '') if params.flanged else '') for order_num, info in params.order_info.items(): d += " || order number: " + order_num + " " + info return d ================================================ FILE: scripts/Connector/Connector_PhoenixContact/mstb.py ================================================ #!/usr/bin/env python3 import sys import os from helpers import * import re import fnmatch import argparse import yaml #sys.path.append(os.path.join(sys.path[0],"..","..")) # load KicadModTree path #add KicadModTree to searchpath using export PYTHONPATH="${PYTHONPATH}/kicad-footprint-generator/" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from mstb_params import seriesParams, dimensions, generate_description, all_params series = ['MSTB', '2,5'] def generate_one_footprint(model, params, configuration): subseries, connector_style = params.series_name.split('-') pitch_mpn = '' if params.pin_pitch == 5.08: pitch_mpn = '-5,08' elif params.pin_pitch == 7.62: pitch_mpn = '-7,62' lib_series = 'GMSTB' if params.pin_pitch >= 7.5 else 'MSTB' lib_name = configuration['lib_name_format_str'].format(series=lib_series, style=series[1], pitch=params.pin_pitch, suffix='') mpn = configuration['mpn_format_string'].format(subseries=subseries, style = connector_style, rating=series[1], num_pins=params.num_pins, pitch=pitch_mpn) footprint_name = configuration['fp_name_format_string'].format(man = configuration['manufacturer'], series = series[0], mpn = mpn, num_rows = 1, num_pins = params.num_pins, mounting_pad = "", pitch = params.pin_pitch, orientation = configuration['orientation_str'][1] if params.angled else configuration['orientation_str'][0], flanged = configuration['flanged_str'][1] if params.flanged else configuration['flanged_str'][0], mount_hole = configuration['mount_hole_str'][1] if params.mount_hole else configuration['mount_hole_str'][0]) length, width, upper_to_pin, left_to_pin, mount_hole_left, mount_hole_right, inner_len = dimensions(params) body_top_left=[left_to_pin,upper_to_pin] body_bottom_right=v_add(body_top_left,[length,width]) body_edge={ 'left': body_top_left[0], 'top': body_top_left[1], 'right': body_bottom_right[0], 'bottom': body_bottom_right[1], } silk_top_left=v_offset(body_top_left, configuration['silk_fab_offset']) silk_bottom_right=v_offset(body_bottom_right, configuration['silk_fab_offset']) center_x = (params.num_pins-1)/2.0*params.pin_pitch kicad_mod = Footprint(footprint_name) mpn = configuration['mpn_format_string_description'].format(subseries=subseries, style = connector_style, rating=series[1], num_pins=params.num_pins, pitch=pitch_mpn) kicad_mod.setDescription(generate_description(params, mpn)) kicad_mod.setTags(configuration['keywords_format_string'].format(mpn=mpn, param_name=model, order_info = ', '.join(params.order_info))) ################################################# Pads ################################################# optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=params.pin_pitch, pincount=params.num_pins, size=[params.pin_Sx, params.pin_Sy], drill=seriesParams.drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=configuration['pin_layers'], **optional_pad_params)) if params.mount_hole: kicad_mod.append(Pad(number='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=mount_hole_left, size=[seriesParams.mount_drill, seriesParams.mount_drill], \ drill=seriesParams.mount_drill, layers=configuration['mount_hole_layers'])) kicad_mod.append(Pad(number='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=mount_hole_right, size=[seriesParams.mount_drill, seriesParams.mount_drill], \ drill=seriesParams.mount_drill, layers=configuration['mount_hole_layers'])) #add an outline around the pins ################################################# Silk and Fab ################################################# kicad_mod.append(RectLine(start=silk_top_left, end=silk_bottom_right, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(RectLine(start=body_top_left, end=body_bottom_right, layer='F.Fab', width=configuration['fab_line_width'])) if params.angled: lock_poly=[ {'x':-1, 'y':0}, {'x':1, 'y':0}, {'x':1.5/2, 'y':-1.5}, {'x':-1.5/2, 'y':-1.5}, {'x':-1, 'y':0} ] lock_poly_fab=[ {'x':-1, 'y':-configuration['silk_fab_offset']}, {'x':1, 'y':-configuration['silk_fab_offset']}, {'x':1.5/2, 'y':-1.5}, {'x':-1.5/2, 'y':-1.5}, {'x':-1, 'y':-configuration['silk_fab_offset']} ] kicad_mod.append(RectLine(start=[silk_top_left[0],silk_bottom_right[1]-1.5], end=[silk_bottom_right[0], silk_bottom_right[1]-1.5-1.8], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(RectLine(start=[body_top_left[0],silk_bottom_right[1]-1.5], end=[body_bottom_right[0], silk_bottom_right[1]-1.5-1.8], layer='F.Fab', width=configuration['fab_line_width'])) if params.flanged: lock_translation = Translation(mount_hole_left[0], silk_bottom_right[1]) lock_translation.append(PolygoneLine(polygone=lock_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lock_translation.append(PolygoneLine(polygone=lock_poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lock_translation) lock_translation = Translation(mount_hole_right[0], silk_bottom_right[1]) lock_translation.append(PolygoneLine(polygone=lock_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lock_translation.append(PolygoneLine(polygone=lock_poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lock_translation) for i in range(params.num_pins): lock_translation = Translation(i*params.pin_pitch, silk_bottom_right[1]) lock_translation.append(PolygoneLine(polygone=lock_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lock_translation.append(PolygoneLine(polygone=lock_poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lock_translation) else: inner_width = 5.3 #measured pi1 = [body_top_left[0]+(length-inner_len)/2.0, body_top_left[1]+1.7] # 1.7mm measured top_thickness = pi1[1]-silk_top_left[1] pi2 = [body_bottom_right[0]-(length-inner_len)/2.0, pi1[1]+inner_width] #kicad_mod.append(RectLine(start=pi1, end=pi2, layer='F.SilkS')) first_center = params.pin_pitch/2.0 line_len = params.pin_pitch-2 outher_line_len = (-left_to_pin-1 + mount_hole_left[0]) if params.flanged else (-left_to_pin-1) kicad_mod.append(Line(start=[silk_top_left[0], pi1[1]-1], end=[silk_top_left[0]+outher_line_len, pi1[1]-1], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line(start=[silk_bottom_right[0], pi1[1]-1], end=[silk_bottom_right[0]-outher_line_len, pi1[1]-1], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(Line(start=[body_top_left[0], pi1[1]-1], end=[body_top_left[0]+outher_line_len, pi1[1]-1], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[body_bottom_right[0], pi1[1]-1], end=[body_bottom_right[0]-outher_line_len, pi1[1]-1], layer='F.Fab', width=configuration['fab_line_width'])) for i in range(params.num_pins -1): chamfer_edge = Translation(i*params.pin_pitch, pi1[1]-1) chamfer_edge.append(Line(start=[first_center-line_len/2.0, 0], end=[first_center+line_len/2.0, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: chamfer_edge.append(Line(start=[first_center-line_len/2.0, 0], end=[first_center+line_len/2.0, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(chamfer_edge) flanged_line_left = (mount_hole_left[0]+1) lock_rect_silk={'start':[-1,0], 'end':[1,-top_thickness], 'layer':'F.SilkS', 'width':configuration['silk_line_width']} lock_rect_fab={'start':[-1,0], 'end':[1,-top_thickness+configuration['silk_fab_offset']], 'layer':'F.Fab', 'width':configuration['fab_line_width']} if params.flanged: lock_translation = Translation(mount_hole_left[0], pi1[1]) lock_translation.append(RectLine(**lock_rect_silk)) if configuration['inner_details_on_fab']: lock_translation.append(RectLine(**lock_rect_fab)) kicad_mod.append(lock_translation) lock_translation = Translation(mount_hole_right[0], pi1[1]) lock_translation.append(RectLine(**lock_rect_silk)) if configuration['inner_details_on_fab']: lock_translation.append(RectLine(**lock_rect_fab)) kicad_mod.append(lock_translation) chamfer_edge = Translation(0, pi1[1]-1) chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(chamfer_edge) chamfer_edge = Translation((params.num_pins-1)*params.pin_pitch+params.mount_hole_to_pin, pi1[1]-1) chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: chamfer_edge.append(Line(start=[flanged_line_left, 0], end=[-1, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(chamfer_edge) for i in range(params.num_pins): lock_translation = Translation(i*params.pin_pitch, pi1[1]) lock_translation.append(RectLine(**lock_rect_silk)) if configuration['inner_details_on_fab']: lock_translation.append(RectLine(**lock_rect_fab)) kicad_mod.append(lock_translation) if params.flanged: kicad_mod.append(Circle(center=mount_hole_left, radius=1.9, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1.9, layer='F.SilkS', width=configuration['silk_line_width'])) if not params.mount_hole: kicad_mod.append(Circle(center=mount_hole_left, radius=1, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: kicad_mod.append(Circle(center=mount_hole_left, radius=1.9, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1.9, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_left, radius=1, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=1, layer='F.Fab', width=configuration['fab_line_width'])) angle = -100.5 arc_width = 4.0 for i in range(params.num_pins): plug_arc = Translation(i*params.pin_pitch,0) plug_arc.append(Arc(start=[-arc_width/2.0,pi2[1]], center=[0,0.55], angle=angle, layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: plug_arc.append(Arc(start=[-arc_width/2.0,pi2[1]], center=[0,0.55], angle=angle, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(plug_arc) for i in range(params.num_pins-1): lower_line = Translation(i*params.pin_pitch,pi2[1]) lower_line.append(Line(start=[arc_width/2.0, 0], end=[params.pin_pitch-arc_width/2.0, 0], layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['inner_details_on_fab']: lower_line.append(Line(start=[arc_width/2.0, 0], end=[params.pin_pitch-arc_width/2.0, 0], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(lower_line) arc_to_side = pi1[0]+arc_width/2.0 poly=[ {'x':pi1[0]-arc_to_side, 'y':pi2[1]}, {'x':pi1[0], 'y':pi2[1]}, {'x':pi1[0], 'y':pi1[1]}, {'x':pi2[0], 'y':pi1[1]}, {'x':pi2[0], 'y':pi2[1]}, {'x':pi2[0]+arc_to_side, 'y':pi2[1]} ] kicad_mod.append(PolygoneLine(polygone=poly)) if configuration['inner_details_on_fab']: kicad_mod.append(PolygoneLine(polygone=poly, layer='F.Fab', width=configuration['fab_line_width'])) if params.mount_hole: kicad_mod.append(Circle(center=mount_hole_left, radius=seriesParams.mount_screw_head_r+configuration['silk_fab_offset'], layer='B.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=seriesParams.mount_screw_head_r+configuration['silk_fab_offset'], layer='B.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Circle(center=mount_hole_right, radius=seriesParams.mount_screw_head_r, layer='B.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Circle(center=mount_hole_left, radius=seriesParams.mount_screw_head_r, layer='B.Fab', width=configuration['fab_line_width'])) ################################################## Courtyard ################################################## #if params.angled: #p1=[p1[0],-seriesParams.pin_Sy/2] crtyd_top_left=v_offset(body_top_left, configuration['courtyard_offset']['connector']) crtyd_bottom_right=v_offset(body_bottom_right, configuration['courtyard_offset']['connector']) kicad_mod.append(RectLine(start=round_crty_point(crtyd_top_left, configuration['courtyard_grid']), end=round_crty_point(crtyd_bottom_right, configuration['courtyard_grid']), layer='F.CrtYd')) if params.mount_hole and configuration['courtyard_for_mountscrews']: kicad_mod.append(Circle(center=mount_hole_right, radius=seriesParams.mount_screw_head_r+configuration['courtyard_offset']['connector'], layer='B.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(Circle(center=mount_hole_left, radius=seriesParams.mount_screw_head_r+configuration['courtyard_offset']['connector'], layer='B.CrtYd', width=configuration['courtyard_line_width'])) ################################################# Text Fields ################################################# addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':crtyd_top_left[1], 'bottom':crtyd_bottom_right[1]}, fp_name=footprint_name, text_y_inside_position='top') ################################################# Pin 1 Marker ################################################# if not params.angled: kicad_mod.append(PolygoneLine(polygone=create_pin1_marker_triangle(silk_top_left[1]-0.2), layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(PolygoneLine( polygone=create_pin1_marker_triangle(bottom_y = -params.pin_Sy/2- 0.75, dimensions = [1, 1], with_top_line = True), layer='F.Fab', width=configuration['fab_line_width'])) else: y_bottom_silk_marker = (silk_top_left[1] if silk_top_left[1] < -params.pin_Sy/2 else -params.pin_Sy/2) - 0.2 kicad_mod.append(PolygoneLine(polygone=create_pin1_marker_triangle(y_bottom_silk_marker), layer='F.SilkS', width=configuration['silk_line_width'])) if configuration['with_fab_layer']: kicad_mod.append(PolygoneLine( polygone=create_pin1_marker_triangle(bottom_y = -0.5, dimensions = [1.9, -body_top_left[1]-0.5], with_top_line = False), layer='F.Fab', width=configuration['fab_line_width'])) #################################################### 3d file ################################################### p3dname = '{prefix:s}{lib_name:s}.3dshapes/{fp_name}.wrl'.format(prefix = configuration.get('3d_model_prefix', '${KISYS3DMOD}/'), lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=p3dname, at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) file_handler = KicadFileHandler(kicad_mod) out_dir = '{:s}.pretty/'.format(lib_name) if not os.path.exists(out_dir): os.makedirs(out_dir) file_handler.writeFile('{:s}.pretty/{:s}.kicad_mod'.format(lib_name, footprint_name)) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='config_phoenix_KLCv3.0.yaml') parser.add_argument('--model_filter', type=str, nargs='?', help='define a filter for what should be generated.', default="*") parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible model_filter_regobj=re.compile(fnmatch.translate(args.model_filter)) for model, params in all_params.items(): if model_filter_regobj.match(model): generate_one_footprint(model, params, configuration) ================================================ FILE: scripts/Connector/Connector_PhoenixContact/mstb_params.py ================================================ from collections import namedtuple from collections import OrderedDict class seriesParams(): drill = 1.4 annular_ring = 0.35 # overwritten by minimum pad to pad clearance. mount_drill = 2.4 mount_screw_head_r = 2.1 mount_screw_info = "ISO 1481-ST 2.2x6.5 C or ISO 7049-ST 2.2x6.5 C (http://www.fasteners.eu/standards/ISO/7049/)" # Connector voltage ratings: # Rated voltage (III/3) 250 V # Rated voltage (III/2) 320 V # Rated voltage (II/2) 400 V # Rated surge voltage (III/3) 4 kV # Rated surge voltage (III/2) 4 kV # Rated surge voltage (II/2) 4 kV # VDE 0110-1/4.97 4kV -> 3mm clearance MSTB_min_pad_to_pad_clearance = 3.0 #Rated surge voltage (III/3) 6 kV #Rated surge voltage (III/2) 6 kV #Rated surge voltage (II/2) 6 kV #Rated voltage (III/3) 400 V #Rated voltage (III/2) 630 V #Rated voltage (II/2) 630 V # VDE 0110-1/4.97 6kV -> 5.5mm GMSTB_min_pad_to_pad_clearance = 5.5 Params = namedtuple("Params",[ 'series_name', 'angled', 'flanged', 'num_pins', 'pin_pitch', 'mount_hole', 'order_info', 'mount_hole_to_pin', 'side_to_pin', 'pin_Sx', 'pin_Sy' ]) def generate_params(num_pins, series_name, pin_pitch, angled, flanged, order_info, mount_hole=False, mount_hole_to_pin=None, side_to_pin=None, min_pad_to_pad_clearance=seriesParams.MSTB_min_pad_to_pad_clearance): nominal_pin_Sx = seriesParams.drill + 2 * seriesParams.annular_ring nominal_pin_Sy = seriesParams.drill + 2 * 1.1 return Params( series_name=series_name, angled=angled, flanged=flanged, num_pins=num_pins, pin_pitch=pin_pitch, mount_hole=mount_hole, order_info=order_info, mount_hole_to_pin=pin_pitch if mount_hole_to_pin is None else mount_hole_to_pin, side_to_pin=(3*pin_pitch if flanged else pin_pitch+2)/2.0 if side_to_pin is None else side_to_pin, pin_Sx= nominal_pin_Sx if (pin_pitch - nominal_pin_Sx) >= min_pad_to_pad_clearance else (pin_pitch - min_pad_to_pad_clearance), pin_Sy = nominal_pin_Sy ) all_params = { ################################################################################################################## # Pin Pitch 5.00mm ################################################################################################################## 'MSTBA_01x02_G_5.00mm' : generate_params( 2, "MSTBA-G", 5.0, True, False, OrderedDict([('1757475', '12A'), ('1923759', '16A (HC)')])), 'MSTBA_01x03_G_5.00mm' : generate_params( 3, "MSTBA-G", 5.0, True, False, OrderedDict([('1757488', '12A'), ('1923762', '16A (HC)')])), 'MSTBA_01x04_G_5.00mm' : generate_params( 4, "MSTBA-G", 5.0, True, False, OrderedDict([('1757491', '12A'), ('1923775', '16A (HC)')])), 'MSTBA_01x05_G_5.00mm' : generate_params( 5, "MSTBA-G", 5.0, True, False, OrderedDict([('1757501', '12A'), ('1923788', '16A (HC)')])), 'MSTBA_01x06_G_5.00mm' : generate_params( 6, "MSTBA-G", 5.0, True, False, OrderedDict([('1757514', '12A'), ('1923791', '16A (HC)')])), 'MSTBA_01x07_G_5.00mm' : generate_params( 7, "MSTBA-G", 5.0, True, False, OrderedDict([('1757493', '12A'), ('1923801', '16A (HC)')])), 'MSTBA_01x08_G_5.00mm' : generate_params( 8, "MSTBA-G", 5.0, True, False, OrderedDict([('1757527', '12A'), ('1923814', '16A (HC)')])), 'MSTBA_01x09_G_5.00mm' : generate_params( 9, "MSTBA-G", 5.0, True, False, OrderedDict([('1757530', '12A'), ('1923827', '16A (HC)')])), 'MSTBA_01x10_G_5.00mm' : generate_params(10, "MSTBA-G", 5.0, True, False, OrderedDict([('1757543', '12A'), ('1923830', '16A (HC)')])), 'MSTBA_01x11_G_5.00mm' : generate_params(11, "MSTBA-G", 5.0, True, False, OrderedDict([('1757556', '12A'), ('1923843', '16A (HC)')])), 'MSTBA_01x12_G_5.00mm' : generate_params(12, "MSTBA-G", 5.0, True, False, OrderedDict([('1757569', '12A'), ('1923856', '16A (HC)')])), 'MSTBA_01x13_G_5.00mm' : generate_params(13, "MSTBA-G", 5.0, True, False, OrderedDict([('1757572', '12A')])), 'MSTBA_01x14_G_5.00mm' : generate_params(14, "MSTBA-G", 5.0, True, False, OrderedDict([('1757585', '12A')])), 'MSTBA_01x15_G_5.00mm' : generate_params(15, "MSTBA-G", 5.0, True, False, OrderedDict([('1757598', '12A')])), 'MSTBA_01x16_G_5.00mm' : generate_params(16, "MSTBA-G", 5.0, True, False, OrderedDict([('1757608', '12A')])), ################################################################################################################### 'MSTB_01x02_GF_5.00mm' : generate_params( 2, "MSTB-GF", 5.0, True, True, OrderedDict([('1776692', '12A'), ('1923979', '16A (HC)')])), 'MSTB_01x03_GF_5.00mm' : generate_params( 3, "MSTB-GF", 5.0, True, True, OrderedDict([('1776702', '12A'), ('1923982', '16A (HC)')])), 'MSTB_01x04_GF_5.00mm' : generate_params( 4, "MSTB-GF", 5.0, True, True, OrderedDict([('1776715', '12A'), ('1923995', '16A (HC)')])), 'MSTB_01x05_GF_5.00mm' : generate_params( 5, "MSTB-GF", 5.0, True, True, OrderedDict([('1776728', '12A'), ('1924004', '16A (HC)')])), 'MSTB_01x06_GF_5.00mm' : generate_params( 6, "MSTB-GF", 5.0, True, True, OrderedDict([('1776731', '12A'), ('1924017', '16A (HC)')])), 'MSTB_01x07_GF_5.00mm' : generate_params( 7, "MSTB-GF", 5.0, True, True, OrderedDict([('1776744', '12A'), ('1924020', '16A (HC)')])), 'MSTB_01x08_GF_5.00mm' : generate_params( 8, "MSTB-GF", 5.0, True, True, OrderedDict([('1776757', '12A'), ('1924033', '16A (HC)')])), 'MSTB_01x09_GF_5.00mm' : generate_params( 9, "MSTB-GF", 5.0, True, True, OrderedDict([('1776760', '12A'), ('1924046', '16A (HC)')])), 'MSTB_01x10_GF_5.00mm' : generate_params(10, "MSTB-GF", 5.0, True, True, OrderedDict([('1776773', '12A'), ('1924059', '16A (HC)')])), 'MSTB_01x11_GF_5.00mm' : generate_params(11, "MSTB-GF", 5.0, True, True, OrderedDict([('1776786', '12A'), ('1924062', '16A (HC)')])), 'MSTB_01x12_GF_5.00mm' : generate_params(12, "MSTB-GF", 5.0, True, True, OrderedDict([('1776799', '12A'), ('1924075', '16A (HC)')])), 'MSTB_01x13_GF_5.00mm' : generate_params(13, "MSTB-GF", 5.0, True, True, OrderedDict([('1776809', '12A')])), 'MSTB_01x14_GF_5.00mm' : generate_params(14, "MSTB-GF", 5.0, True, True, OrderedDict([('1776812', '12A')])), 'MSTB_01x15_GF_5.00mm' : generate_params(15, "MSTB-GF", 5.0, True, True, OrderedDict([('1776825', '12A')])), 'MSTB_01x16_GF_5.00mm' : generate_params(16, "MSTB-GF", 5.0, True, True, OrderedDict([('1776838', '12A')])), ################################################################################################################### 'MSTB_01x02_GF_5.00mm_MH' : generate_params( 2, "MSTB-GF", 5.0, True, True, OrderedDict([('1776692', '12A'), ('1923979', '16A (HC)')]), mount_hole=True), 'MSTB_01x03_GF_5.00mm_MH' : generate_params( 3, "MSTB-GF", 5.0, True, True, OrderedDict([('1776702', '12A'), ('1923982', '16A (HC)')]), mount_hole=True), 'MSTB_01x04_GF_5.00mm_MH' : generate_params( 4, "MSTB-GF", 5.0, True, True, OrderedDict([('1776715', '12A'), ('1923995', '16A (HC)')]), mount_hole=True), 'MSTB_01x05_GF_5.00mm_MH' : generate_params( 5, "MSTB-GF", 5.0, True, True, OrderedDict([('1776728', '12A'), ('1924004', '16A (HC)')]), mount_hole=True), 'MSTB_01x06_GF_5.00mm_MH' : generate_params( 6, "MSTB-GF", 5.0, True, True, OrderedDict([('1776731', '12A'), ('1924017', '16A (HC)')]), mount_hole=True), 'MSTB_01x07_GF_5.00mm_MH' : generate_params( 7, "MSTB-GF", 5.0, True, True, OrderedDict([('1776744', '12A'), ('1924020', '16A (HC)')]), mount_hole=True), 'MSTB_01x08_GF_5.00mm_MH' : generate_params( 8, "MSTB-GF", 5.0, True, True, OrderedDict([('1776757', '12A'), ('1924033', '16A (HC)')]), mount_hole=True), 'MSTB_01x09_GF_5.00mm_MH' : generate_params( 9, "MSTB-GF", 5.0, True, True, OrderedDict([('1776760', '12A'), ('1924046', '16A (HC)')]), mount_hole=True), 'MSTB_01x10_GF_5.00mm_MH' : generate_params(10, "MSTB-GF", 5.0, True, True, OrderedDict([('1776773', '12A'), ('1924059', '16A (HC)')]), mount_hole=True), 'MSTB_01x11_GF_5.00mm_MH' : generate_params(11, "MSTB-GF", 5.0, True, True, OrderedDict([('1776786', '12A'), ('1924062', '16A (HC)')]), mount_hole=True), 'MSTB_01x12_GF_5.00mm_MH' : generate_params(12, "MSTB-GF", 5.0, True, True, OrderedDict([('1776799', '12A'), ('1924075', '16A (HC)')]), mount_hole=True), 'MSTB_01x13_GF_5.00mm_MH' : generate_params(13, "MSTB-GF", 5.0, True, True, OrderedDict([('1776809', '12A')]), mount_hole=True), 'MSTB_01x14_GF_5.00mm_MH' : generate_params(14, "MSTB-GF", 5.0, True, True, OrderedDict([('1776812', '12A')]), mount_hole=True), 'MSTB_01x15_GF_5.00mm_MH' : generate_params(15, "MSTB-GF", 5.0, True, True, OrderedDict([('1776825', '12A')]), mount_hole=True), 'MSTB_01x16_GF_5.00mm_MH' : generate_params(16, "MSTB-GF", 5.0, True, True, OrderedDict([('1776838', '12A')]), mount_hole=True), ################################################################################################################### 'MSTBVA_01x02_G_5.00mm' : generate_params( 2, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755516', '12A'), ('1924198', '16A (HC)')])), 'MSTBVA_01x03_G_5.00mm' : generate_params( 3, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755529', '12A'), ('1924208', '16A (HC)')])), 'MSTBVA_01x04_G_5.00mm' : generate_params( 4, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755532', '12A'), ('1924211', '16A (HC)')])), 'MSTBVA_01x05_G_5.00mm' : generate_params( 5, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755545', '12A'), ('1924224', '16A (HC)')])), 'MSTBVA_01x06_G_5.00mm' : generate_params( 6, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755558', '12A'), ('1924237', '16A (HC)')])), 'MSTBVA_01x07_G_5.00mm' : generate_params( 7, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755561', '12A'), ('1924240', '16A (HC)')])), 'MSTBVA_01x08_G_5.00mm' : generate_params( 8, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755574', '12A'), ('1924253', '16A (HC)')])), 'MSTBVA_01x09_G_5.00mm' : generate_params( 9, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755587', '12A'), ('1924266', '16A (HC)')])), 'MSTBVA_01x10_G_5.00mm' : generate_params(10, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755503', '12A'), ('1924279', '16A (HC)')])), 'MSTBVA_01x11_G_5.00mm' : generate_params(11, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755590', '12A'), ('1924282', '16A (HC)')])), 'MSTBVA_01x12_G_5.00mm' : generate_params(12, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755600', '12A'), ('1924295', '16A (HC)')])), 'MSTBVA_01x13_G_5.00mm' : generate_params(13, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755613', '12A')])), 'MSTBVA_01x14_G_5.00mm' : generate_params(14, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755626', '12A')])), 'MSTBVA_01x15_G_5.00mm' : generate_params(15, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755639', '12A')])), 'MSTBVA_01x16_G_5.00mm' : generate_params(16, "MSTBVA-G", 5.0, False, False, OrderedDict([('1755642', '12A')])), ################################################################################################################### 'MSTBV_01x02_GF_5.00mm' : generate_params( 2, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776883', '12A'), ('1924415', '16A (HC)')])), 'MSTBV_01x03_GF_5.00mm' : generate_params( 3, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776896', '12A'), ('1924428', '16A (HC)')])), 'MSTBV_01x04_GF_5.00mm' : generate_params( 4, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776906', '12A'), ('1924431', '16A (HC)')])), 'MSTBV_01x05_GF_5.00mm' : generate_params( 5, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776919', '12A'), ('1924444', '16A (HC)')])), 'MSTBV_01x06_GF_5.00mm' : generate_params( 6, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776922', '12A'), ('1924457', '16A (HC)')])), 'MSTBV_01x07_GF_5.00mm' : generate_params( 7, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776935', '12A'), ('1924460', '16A (HC)')])), 'MSTBV_01x08_GF_5.00mm' : generate_params( 8, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776948', '12A'), ('1924473', '16A (HC)')])), 'MSTBV_01x09_GF_5.00mm' : generate_params( 9, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776951', '12A'), ('1924486', '16A (HC)')])), 'MSTBV_01x10_GF_5.00mm' : generate_params(10, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776964', '12A'), ('1924499', '16A (HC)')])), 'MSTBV_01x11_GF_5.00mm' : generate_params(11, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776977', '12A'), ('1924509', '16A (HC)')])), 'MSTBV_01x12_GF_5.00mm' : generate_params(12, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776980', '12A'), ('1924512', '16A (HC)')])), 'MSTBV_01x13_GF_5.00mm' : generate_params(13, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776993', '12A')])), 'MSTBV_01x14_GF_5.00mm' : generate_params(14, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776002', '12A')])), 'MSTBV_01x15_GF_5.00mm' : generate_params(15, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776015', '12A')])), 'MSTBV_01x16_GF_5.00mm' : generate_params(16, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776028', '12A')])), ################################################################################################################### 'MSTBV_01x02_GF_5.00mm_MH' : generate_params( 2, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776883', '12A'), ('1924415', '16A (HC)')]), mount_hole=True), 'MSTBV_01x03_GF_5.00mm_MH' : generate_params( 3, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776896', '12A'), ('1924428', '16A (HC)')]), mount_hole=True), 'MSTBV_01x04_GF_5.00mm_MH' : generate_params( 4, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776906', '12A'), ('1924431', '16A (HC)')]), mount_hole=True), 'MSTBV_01x05_GF_5.00mm_MH' : generate_params( 5, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776919', '12A'), ('1924444', '16A (HC)')]), mount_hole=True), 'MSTBV_01x06_GF_5.00mm_MH' : generate_params( 6, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776922', '12A'), ('1924457', '16A (HC)')]), mount_hole=True), 'MSTBV_01x07_GF_5.00mm_MH' : generate_params( 7, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776935', '12A'), ('1924460', '16A (HC)')]), mount_hole=True), 'MSTBV_01x08_GF_5.00mm_MH' : generate_params( 8, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776948', '12A'), ('1924473', '16A (HC)')]), mount_hole=True), 'MSTBV_01x09_GF_5.00mm_MH' : generate_params( 9, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776951', '12A'), ('1924486', '16A (HC)')]), mount_hole=True), 'MSTBV_01x10_GF_5.00mm_MH' : generate_params(10, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776964', '12A'), ('1924499', '16A (HC)')]), mount_hole=True), 'MSTBV_01x11_GF_5.00mm_MH' : generate_params(11, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776977', '12A'), ('1924509', '16A (HC)')]), mount_hole=True), 'MSTBV_01x12_GF_5.00mm_MH' : generate_params(12, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776980', '12A'), ('1924512', '16A (HC)')]), mount_hole=True), 'MSTBV_01x13_GF_5.00mm_MH' : generate_params(13, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776993', '12A')]), mount_hole=True), 'MSTBV_01x14_GF_5.00mm_MH' : generate_params(14, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776002', '12A')]), mount_hole=True), 'MSTBV_01x15_GF_5.00mm_MH' : generate_params(15, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776015', '12A')]), mount_hole=True), 'MSTBV_01x16_GF_5.00mm_MH' : generate_params(16, "MSTBV-GF", 5.0, False, True, OrderedDict([('1776028', '12A')]), mount_hole=True), ################################################################################################################## # Pin Pitch 5.08mm ################################################################################################################## 'MSTBA_01x02_G_5.08mm' : generate_params( 2, "MSTBA-G", 5.08, True, False, OrderedDict([('1757242', '12A'), ('1923869', '16A (HC)')])), 'MSTBA_01x03_G_5.08mm' : generate_params( 3, "MSTBA-G", 5.08, True, False, OrderedDict([('1757255', '12A'), ('1923872', '16A (HC)')])), 'MSTBA_01x04_G_5.08mm' : generate_params( 4, "MSTBA-G", 5.08, True, False, OrderedDict([('1757268', '12A'), ('1923885', '16A (HC)')])), 'MSTBA_01x05_G_5.08mm' : generate_params( 5, "MSTBA-G", 5.08, True, False, OrderedDict([('1757271', '12A'), ('1923898', '16A (HC)')])), 'MSTBA_01x06_G_5.08mm' : generate_params( 6, "MSTBA-G", 5.08, True, False, OrderedDict([('1757284', '12A'), ('1923908', '16A (HC)')])), 'MSTBA_01x07_G_5.08mm' : generate_params( 7, "MSTBA-G", 5.08, True, False, OrderedDict([('1757297', '12A'), ('1923911', '16A (HC)')])), 'MSTBA_01x08_G_5.08mm' : generate_params( 8, "MSTBA-G", 5.08, True, False, OrderedDict([('1757307', '12A'), ('1923924', '16A (HC)')])), 'MSTBA_01x09_G_5.08mm' : generate_params( 9, "MSTBA-G", 5.08, True, False, OrderedDict([('1757310', '12A'), ('1923937', '16A (HC)')])), 'MSTBA_01x10_G_5.08mm' : generate_params(10, "MSTBA-G", 5.08, True, False, OrderedDict([('1757323', '12A'), ('1923940', '16A (HC)')])), 'MSTBA_01x11_G_5.08mm' : generate_params(11, "MSTBA-G", 5.08, True, False, OrderedDict([('1757336', '12A'), ('1923953', '16A (HC)')])), 'MSTBA_01x12_G_5.08mm' : generate_params(12, "MSTBA-G", 5.08, True, False, OrderedDict([('1757349', '12A'), ('1923966', '16A (HC)')])), 'MSTBA_01x13_G_5.08mm' : generate_params(13, "MSTBA-G", 5.08, True, False, OrderedDict([('1757352', '12A')])), 'MSTBA_01x14_G_5.08mm' : generate_params(14, "MSTBA-G", 5.08, True, False, OrderedDict([('1757365', '12A')])), 'MSTBA_01x15_G_5.08mm' : generate_params(15, "MSTBA-G", 5.08, True, False, OrderedDict([('1757378', '12A')])), 'MSTBA_01x16_G_5.08mm' : generate_params(16, "MSTBA-G", 5.08, True, False, OrderedDict([('1757381', '12A')])), ################################################################################################################### 'MSTB_01x02_GF_5.08mm' : generate_params( 2, "MSTB-GF", 5.08, True, True, OrderedDict([('1776508', '12A'), ('1924088', '16A (HC)')])), 'MSTB_01x03_GF_5.08mm' : generate_params( 3, "MSTB-GF", 5.08, True, True, OrderedDict([('1776511', '12A'), ('1924091', '16A (HC)')])), 'MSTB_01x04_GF_5.08mm' : generate_params( 4, "MSTB-GF", 5.08, True, True, OrderedDict([('1776524', '12A'), ('1924101', '16A (HC)')])), 'MSTB_01x05_GF_5.08mm' : generate_params( 5, "MSTB-GF", 5.08, True, True, OrderedDict([('1776537', '12A'), ('1924114', '16A (HC)')])), 'MSTB_01x06_GF_5.08mm' : generate_params( 6, "MSTB-GF", 5.08, True, True, OrderedDict([('1776540', '12A'), ('1924127', '16A (HC)')])), 'MSTB_01x07_GF_5.08mm' : generate_params( 7, "MSTB-GF", 5.08, True, True, OrderedDict([('1776553', '12A'), ('1924130', '16A (HC)')])), 'MSTB_01x08_GF_5.08mm' : generate_params( 8, "MSTB-GF", 5.08, True, True, OrderedDict([('1776566', '12A'), ('1924143', '16A (HC)')])), 'MSTB_01x09_GF_5.08mm' : generate_params( 9, "MSTB-GF", 5.08, True, True, OrderedDict([('1776579', '12A'), ('1924156', '16A (HC)')])), 'MSTB_01x10_GF_5.08mm' : generate_params(10, "MSTB-GF", 5.08, True, True, OrderedDict([('1776582', '12A'), ('1924169', '16A (HC)')])), 'MSTB_01x11_GF_5.08mm' : generate_params(11, "MSTB-GF", 5.08, True, True, OrderedDict([('1776595', '12A'), ('1924172', '16A (HC)')])), 'MSTB_01x12_GF_5.08mm' : generate_params(12, "MSTB-GF", 5.08, True, True, OrderedDict([('1776605', '12A'), ('1924185', '16A (HC)')])), 'MSTB_01x13_GF_5.08mm' : generate_params(13, "MSTB-GF", 5.08, True, True, OrderedDict([('1776618', '12A')])), 'MSTB_01x14_GF_5.08mm' : generate_params(14, "MSTB-GF", 5.08, True, True, OrderedDict([('1776621', '12A')])), 'MSTB_01x15_GF_5.08mm' : generate_params(15, "MSTB-GF", 5.08, True, True, OrderedDict([('1776634', '12A')])), 'MSTB_01x16_GF_5.08mm' : generate_params(16, "MSTB-GF", 5.08, True, True, OrderedDict([('1776647', '12A')])), ################################################################################################################### 'MSTB_01x02_GF_5.08mm_MH' : generate_params( 2, "MSTB-GF", 5.08, True, True, OrderedDict([('1776508', '12A'), ('1924088', '16A (HC)')]), mount_hole=True), 'MSTB_01x03_GF_5.08mm_MH' : generate_params( 3, "MSTB-GF", 5.08, True, True, OrderedDict([('1776511', '12A'), ('1924091', '16A (HC)')]), mount_hole=True), 'MSTB_01x04_GF_5.08mm_MH' : generate_params( 4, "MSTB-GF", 5.08, True, True, OrderedDict([('1776524', '12A'), ('1924101', '16A (HC)')]), mount_hole=True), 'MSTB_01x05_GF_5.08mm_MH' : generate_params( 5, "MSTB-GF", 5.08, True, True, OrderedDict([('1776537', '12A'), ('1924114', '16A (HC)')]), mount_hole=True), 'MSTB_01x06_GF_5.08mm_MH' : generate_params( 6, "MSTB-GF", 5.08, True, True, OrderedDict([('1776540', '12A'), ('1924127', '16A (HC)')]), mount_hole=True), 'MSTB_01x07_GF_5.08mm_MH' : generate_params( 7, "MSTB-GF", 5.08, True, True, OrderedDict([('1776553', '12A'), ('1924130', '16A (HC)')]), mount_hole=True), 'MSTB_01x08_GF_5.08mm_MH' : generate_params( 8, "MSTB-GF", 5.08, True, True, OrderedDict([('1776566', '12A'), ('1924143', '16A (HC)')]), mount_hole=True), 'MSTB_01x09_GF_5.08mm_MH' : generate_params( 9, "MSTB-GF", 5.08, True, True, OrderedDict([('1776579', '12A'), ('1924156', '16A (HC)')]), mount_hole=True), 'MSTB_01x10_GF_5.08mm_MH' : generate_params(10, "MSTB-GF", 5.08, True, True, OrderedDict([('1776582', '12A'), ('1924169', '16A (HC)')]), mount_hole=True), 'MSTB_01x11_GF_5.08mm_MH' : generate_params(11, "MSTB-GF", 5.08, True, True, OrderedDict([('1776595', '12A'), ('1924172', '16A (HC)')]), mount_hole=True), 'MSTB_01x12_GF_5.08mm_MH' : generate_params(12, "MSTB-GF", 5.08, True, True, OrderedDict([('1776605', '12A'), ('1924185', '16A (HC)')]), mount_hole=True), 'MSTB_01x13_GF_5.08mm_MH' : generate_params(13, "MSTB-GF", 5.08, True, True, OrderedDict([('1776618', '12A')]), mount_hole=True), 'MSTB_01x14_GF_5.08mm_MH' : generate_params(14, "MSTB-GF", 5.08, True, True, OrderedDict([('1776621', '12A')]), mount_hole=True), 'MSTB_01x15_GF_5.08mm_MH' : generate_params(15, "MSTB-GF", 5.08, True, True, OrderedDict([('1776634', '12A')]), mount_hole=True), 'MSTB_01x16_GF_5.08mm_MH' : generate_params(16, "MSTB-GF", 5.08, True, True, OrderedDict([('1776647', '12A')]), mount_hole=True), ################################################################################################################### 'MSTBVA_01x02_G_5.08mm' : generate_params( 2, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755736', '12A'), ('1924305', '16A (HC)')])), 'MSTBVA_01x03_G_5.08mm' : generate_params( 3, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755749', '12A'), ('1924318', '16A (HC)')])), 'MSTBVA_01x04_G_5.08mm' : generate_params( 4, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755752', '12A'), ('1924321', '16A (HC)')])), 'MSTBVA_01x05_G_5.08mm' : generate_params( 5, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755765', '12A'), ('1924334', '16A (HC)')])), 'MSTBVA_01x06_G_5.08mm' : generate_params( 6, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755778', '12A'), ('1924347', '16A (HC)')])), 'MSTBVA_01x07_G_5.08mm' : generate_params( 7, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755781', '12A'), ('1924350', '16A (HC)')])), 'MSTBVA_01x08_G_5.08mm' : generate_params( 8, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755794', '12A'), ('1924363', '16A (HC)')])), 'MSTBVA_01x09_G_5.08mm' : generate_params( 9, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755804', '12A'), ('1924376', '16A (HC)')])), 'MSTBVA_01x10_G_5.08mm' : generate_params(10, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755817', '12A'), ('1924389', '16A (HC)')])), 'MSTBVA_01x11_G_5.08mm' : generate_params(11, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755820', '12A'), ('1924392', '16A (HC)')])), 'MSTBVA_01x12_G_5.08mm' : generate_params(12, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755833', '12A'), ('1924402', '16A (HC)')])), 'MSTBVA_01x13_G_5.08mm' : generate_params(13, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755846', '12A')])), 'MSTBVA_01x14_G_5.08mm' : generate_params(14, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755859', '12A')])), 'MSTBVA_01x15_G_5.08mm' : generate_params(15, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755862', '12A')])), 'MSTBVA_01x16_G_5.08mm' : generate_params(16, "MSTBVA-G", 5.08, False, False, OrderedDict([('1755875', '12A')])), ################################################################################################################### 'MSTBV_01x02_GF_5.08mm' : generate_params( 2, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777073', '12A'), ('1924525', '16A (HC)')])), 'MSTBV_01x03_GF_5.08mm' : generate_params( 3, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777086', '12A'), ('1924538', '16A (HC)')])), 'MSTBV_01x04_GF_5.08mm' : generate_params( 4, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777099', '12A'), ('1924541', '16A (HC)')])), 'MSTBV_01x05_GF_5.08mm' : generate_params( 5, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777109', '12A'), ('1924554', '16A (HC)')])), 'MSTBV_01x06_GF_5.08mm' : generate_params( 6, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777112', '12A'), ('1924567', '16A (HC)')])), 'MSTBV_01x07_GF_5.08mm' : generate_params( 7, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777125', '12A'), ('1924570', '16A (HC)')])), 'MSTBV_01x08_GF_5.08mm' : generate_params( 8, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777138', '12A'), ('1924583', '16A (HC)')])), 'MSTBV_01x09_GF_5.08mm' : generate_params( 9, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777141', '12A'), ('1924596', '16A (HC)')])), 'MSTBV_01x10_GF_5.08mm' : generate_params(10, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777154', '12A'), ('1924606', '16A (HC)')])), 'MSTBV_01x11_GF_5.08mm' : generate_params(11, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777167', '12A'), ('1924619', '16A (HC)')])), 'MSTBV_01x12_GF_5.08mm' : generate_params(12, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777170', '12A'), ('1924622', '16A (HC)')])), 'MSTBV_01x13_GF_5.08mm' : generate_params(13, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777183', '12A')])), 'MSTBV_01x14_GF_5.08mm' : generate_params(14, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777196', '12A')])), 'MSTBV_01x15_GF_5.08mm' : generate_params(15, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777206', '12A')])), 'MSTBV_01x16_GF_5.08mm' : generate_params(16, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777219', '12A')])), ################################################################################################################### 'MSTBV_01x02_GF_5.08mm_MH' : generate_params( 2, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777073', '12A'), ('1924525', '16A (HC)')]), mount_hole=True), 'MSTBV_01x03_GF_5.08mm_MH' : generate_params( 3, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777086', '12A'), ('1924538', '16A (HC)')]), mount_hole=True), 'MSTBV_01x04_GF_5.08mm_MH' : generate_params( 4, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777099', '12A'), ('1924541', '16A (HC)')]), mount_hole=True), 'MSTBV_01x05_GF_5.08mm_MH' : generate_params( 5, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777109', '12A'), ('1924554', '16A (HC)')]), mount_hole=True), 'MSTBV_01x06_GF_5.08mm_MH' : generate_params( 6, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777112', '12A'), ('1924567', '16A (HC)')]), mount_hole=True), 'MSTBV_01x07_GF_5.08mm_MH' : generate_params( 7, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777125', '12A'), ('1924570', '16A (HC)')]), mount_hole=True), 'MSTBV_01x08_GF_5.08mm_MH' : generate_params( 8, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777138', '12A'), ('1924583', '16A (HC)')]), mount_hole=True), 'MSTBV_01x09_GF_5.08mm_MH' : generate_params( 9, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777141', '12A'), ('1924596', '16A (HC)')]), mount_hole=True), 'MSTBV_01x10_GF_5.08mm_MH' : generate_params(10, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777154', '12A'), ('1924606', '16A (HC)')]), mount_hole=True), 'MSTBV_01x11_GF_5.08mm_MH' : generate_params(11, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777167', '12A'), ('1924619', '16A (HC)')]), mount_hole=True), 'MSTBV_01x12_GF_5.08mm_MH' : generate_params(12, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777170', '12A'), ('1924622', '16A (HC)')]), mount_hole=True), 'MSTBV_01x13_GF_5.08mm_MH' : generate_params(13, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777183', '12A')]), mount_hole=True), 'MSTBV_01x14_GF_5.08mm_MH' : generate_params(14, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777196', '12A')]), mount_hole=True), 'MSTBV_01x15_GF_5.08mm_MH' : generate_params(15, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777206', '12A')]), mount_hole=True), 'MSTBV_01x16_GF_5.08mm_MH' : generate_params(16, "MSTBV-GF", 5.08, False, True, OrderedDict([('1777219', '12A')]), mount_hole=True), ################################################################################################################## # High Voltage Versions (pin pitch 7.5mm) ################################################################################################################## 'GMSTBA_01x02_G_7.50mm' : generate_params( 2, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766343', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x03_G_7.50mm' : generate_params( 3, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766356', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x04_G_7.50mm' : generate_params( 4, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766369', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x05_G_7.50mm' : generate_params( 5, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766372', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x06_G_7.50mm' : generate_params( 6, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766385', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x07_G_7.50mm' : generate_params( 7, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766398', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x08_G_7.50mm' : generate_params( 8, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766408', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x09_G_7.50mm' : generate_params( 9, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766411', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x10_G_7.50mm' : generate_params(10, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766424', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x11_G_7.50mm' : generate_params(11, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766437', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x12_G_7.50mm' : generate_params(12, "GMSTBA-G", 7.50, True, False, OrderedDict([('1766440', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), ################################################################################################################## 'GMSTBVA_01x02_G_7.50mm' : generate_params( 2, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766660', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x03_G_7.50mm' : generate_params( 3, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766673', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x04_G_7.50mm' : generate_params( 4, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766686', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x05_G_7.50mm' : generate_params( 5, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766699', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x06_G_7.50mm' : generate_params( 6, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766709', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x07_G_7.50mm' : generate_params( 7, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766712', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x08_G_7.50mm' : generate_params( 8, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766725', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x09_G_7.50mm' : generate_params( 9, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766738', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x10_G_7.50mm' : generate_params(10, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766741', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x11_G_7.50mm' : generate_params(11, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766754', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x12_G_7.50mm' : generate_params(12, "GMSTBVA-G", 7.50, False, False, OrderedDict([('1766767', '12A 630V')]), side_to_pin=3.75, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), ################################################################################################################## # High Voltage Versions (pin pitch 7.62mm) ################################################################################################################## 'GMSTBA_01x02_G_7.62mm' : generate_params( 2, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766233', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x03_G_7.62mm' : generate_params( 3, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766246', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x04_G_7.62mm' : generate_params( 4, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766259', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x05_G_7.62mm' : generate_params( 5, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766262', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x06_G_7.62mm' : generate_params( 6, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766275', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x07_G_7.62mm' : generate_params( 7, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766288', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x08_G_7.62mm' : generate_params( 8, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766291', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x09_G_7.62mm' : generate_params( 9, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766301', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x10_G_7.62mm' : generate_params(10, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766314', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x11_G_7.62mm' : generate_params(11, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766327', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBA_01x12_G_7.62mm' : generate_params(12, "GMSTBA-G", 7.62, True, False, OrderedDict([('1766330', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), ################################################################################################################### 'GMSTB_01x02_GF_7.62mm' : generate_params( 2, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806229', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x03_GF_7.62mm' : generate_params( 3, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806232', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x04_GF_7.62mm' : generate_params( 4, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806245', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x05_GF_7.62mm' : generate_params( 5, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806258', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x06_GF_7.62mm' : generate_params( 6, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806261', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x07_GF_7.62mm' : generate_params( 7, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806274', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x08_GF_7.62mm' : generate_params( 8, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806287', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x09_GF_7.62mm' : generate_params( 9, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806290', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x10_GF_7.62mm' : generate_params(10, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806300', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x11_GF_7.62mm' : generate_params(11, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806313', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x12_GF_7.62mm' : generate_params(12, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806326', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), ################################################################################################################### 'GMSTB_01x02_GF_7.62mm_MH' : generate_params( 2, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806229', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x03_GF_7.62mm_MH' : generate_params( 3, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806232', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x04_GF_7.62mm_MH' : generate_params( 4, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806245', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x05_GF_7.62mm_MH' : generate_params( 5, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806258', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x06_GF_7.62mm_MH' : generate_params( 6, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806261', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x07_GF_7.62mm_MH' : generate_params( 7, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806274', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x08_GF_7.62mm_MH' : generate_params( 8, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806287', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x09_GF_7.62mm_MH' : generate_params( 9, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806290', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x10_GF_7.62mm_MH' : generate_params(10, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806300', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x11_GF_7.62mm_MH' : generate_params(11, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806313', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTB_01x12_GF_7.62mm_MH' : generate_params(12, "GMSTB-GF", 7.62, True, True, OrderedDict([('1806326', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), ################################################################################################################### 'GMSTBVA_01x02_G_7.62mm' : generate_params( 2, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766770', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x03_G_7.62mm' : generate_params( 3, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766783', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x04_G_7.62mm' : generate_params( 4, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766796', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x05_G_7.62mm' : generate_params( 5, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766806', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x06_G_7.62mm' : generate_params( 6, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766819', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x07_G_7.62mm' : generate_params( 7, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766822', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x08_G_7.62mm' : generate_params( 8, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766835', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x09_G_7.62mm' : generate_params( 9, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766848', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x10_G_7.62mm' : generate_params(10, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766851', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x11_G_7.62mm' : generate_params(11, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766864', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBVA_01x12_G_7.62mm' : generate_params(12, "GMSTBVA-G", 7.62, False, False, OrderedDict([('1766877', '12A 630V')]), side_to_pin=3.81, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), ################################################################################################################### 'GMSTBV_01x02_GF_7.62mm' : generate_params( 2, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829154', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x03_GF_7.62mm' : generate_params( 3, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829167', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x04_GF_7.62mm' : generate_params( 4, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829170', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x05_GF_7.62mm' : generate_params( 5, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829183', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x06_GF_7.62mm' : generate_params( 6, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829196', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x07_GF_7.62mm' : generate_params( 7, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829206', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x08_GF_7.62mm' : generate_params( 8, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829219', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x09_GF_7.62mm' : generate_params( 9, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829222', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x10_GF_7.62mm' : generate_params(10, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829235', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x11_GF_7.62mm' : generate_params(11, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829248', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x12_GF_7.62mm' : generate_params(12, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829251', '12A 630V')]), mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), ################################################################################################################### 'GMSTBV_01x02_GF_7.62mm_MH' : generate_params( 2, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829154', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x03_GF_7.62mm_MH' : generate_params( 3, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829167', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x04_GF_7.62mm_MH' : generate_params( 4, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829170', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x05_GF_7.62mm_MH' : generate_params( 5, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829183', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x06_GF_7.62mm_MH' : generate_params( 6, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829196', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x07_GF_7.62mm_MH' : generate_params( 7, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829206', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x08_GF_7.62mm_MH' : generate_params( 8, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829219', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x09_GF_7.62mm_MH' : generate_params( 9, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829222', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x10_GF_7.62mm_MH' : generate_params(10, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829235', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x11_GF_7.62mm_MH' : generate_params(11, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829248', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance), 'GMSTBV_01x12_GF_7.62mm_MH' : generate_params(12, "GMSTBV-GF", 7.62, False, True, OrderedDict([('1829251', '12A 630V')]), mount_hole=True, mount_hole_to_pin=6.1, side_to_pin=9.1, min_pad_to_pad_clearance=seriesParams.GMSTB_min_pad_to_pad_clearance) } #lock_cutout= def dimensions(params): lenght = (params.num_pins-1)*params.pin_pitch + 2*params.side_to_pin width = 12 if params.angled else 8.6 upper_to_pin = -2 if params.angled else -8.6+3.8 left_to_pin = -params.side_to_pin mount_hole_y = 2.5 if params.angled else 0.0 mount_hole_left = [-params.mount_hole_to_pin,mount_hole_y] mount_hole_right = [(params.num_pins-1)*params.pin_pitch+params.mount_hole_to_pin,mount_hole_y] inner_len = params.num_pins*params.pin_pitch-1.6 + (0 if params.pin_pitch>5.08 else 2) return lenght, width, upper_to_pin, left_to_pin,\ mount_hole_left, mount_hole_right, inner_len def generate_description(params, mpn): d = "Generic Phoenix Contact connector footprint for: " + mpn + "; number of pins: " + ("%02d" %params.num_pins) + "; pin pitch: " + (('%.2f' % params.pin_pitch))\ +"mm" + ('; Angled' if params.angled else '; Vertical')\ + ('; threaded flange' + ('; footprint includes mount hole for mounting screw: ' + seriesParams.mount_screw_info if params.mount_hole else '') if params.flanged else '') for order_num, info in params.order_info.items(): d += " || order number: " + order_num + " " + info return d ================================================ FILE: scripts/Connector/Connector_SMD_single_row_plus_mounting_pad/conn_hirose.yaml ================================================ group_definitions: manufacturer: 'Hirose' device_definition: DF3EA: series: '' mpn_format_string: 'DF3EA-{pincount:02d}P-2H' orientation: 'H' datasheet: 'https://www.hirose.com/product/document?clcode=CL0543-0332-0-51&productname=DF3EA-5P-2H(51)&series=DF3&documenttype=2DDrawing&lang=en&documentid=0001163317' pinrange: ['list', [2,3,4,5,6,7,8,9,10,11,12,13,14,15]] text_inside_pos: 'center' pitch: 2 pad1_position: 'top-left' mounting_pad_size: [2.3, 3.3] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 3.37 #(D-B)/2 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 8.8 rel_pad_y_inside_edge: 5.7 pad_size_x: 1.2 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.45 body_size_y: 5.9 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 3.25 # DF13C: # series: 'DF13C' # mpn_format_string: 'CL535-04{pincount:02d}-{param_1:s}-51' # mpn_param_1: ['2','5','8','0','3','6','9','1','4','3','6','1','4'] # orientation: 'V' # datasheet: 'https://www.hirose.com/product/en/products/DF13/DF13C-10P-1.25V%2851%29/' # pinrange: ['list', [2,3,4,5,6,7,8,9,10,11,12,14,15]] # text_inside_pos: 'center' # pitch: 1.25 # pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 # mounting_pad_size: [1.6, 2.2] # # x position mounting inner mounting pad edge relative to nearest pad center # center_pad_to_mounting_pad_edge: 1.45 # # y dimensions for pad given relative to mounting pad edge # rel_pad_y_outside_edge: 4.7 # rel_pad_y_inside_edge: 2.9 # pad_size_x: 0.7 # # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) # rel_body_edge_y: 0.6 # body_size_y: 3.4 # # body_fin_protrusion: 1.6 # # body_fin_width: 0.8 # # x body edge relative to nearest pin # rel_body_edge_x: 2.2 # # todo: keepout DF52: series: '' mpn_format_string: 'DF52-{pincount:d}S-0.8H' orientation: 'H' datasheet: 'https://www.hirose.com/product/en/products/DF52/DF52-3S-0.8H%2821%29/' pinrange: ['list', [2,3,4,5,6,7,8,9,10,11,12,14,15]] text_inside_pos: 'bottom' pitch: 0.8 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.9, 1.6] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.8 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 3.22 rel_pad_y_inside_edge: 2.22 pad_size_x: 0.5 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.1 body_size_y: 2.77 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 # FH12_34: # series: '' # mpn_format_string: 'FH12-{pincount:d}S-0.8H' # orientation: 'H' # datasheet: 'https://www.hirose.com/product/en/products/FH12/FH12-24S-0.5SH(55)/' # pinrange: ['list', [6,8,10,11,12,13,14,15,16,17,18,19,20,22,24,25,26,28,30,32,33,34]] # text_inside_pos: 'bottom' # pitch: 0.5 # pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 # mounting_pad_size: [1.8, 2.2] # # x position mounting inner mounting pad edge relative to nearest pad center # center_pad_to_mounting_pad_edge: 1 # # y dimensions for pad given relative to mounting pad edge # rel_pad_y_outside_edge: 5 # rel_pad_y_inside_edge: 3.7 # pad_size_x: 0.3 # # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) # rel_body_edge_y: 1.9 # body_size_y: 5.6 # # body_fin_protrusion: 1.6 # # body_fin_width: 0.8 # # x body edge relative to nearest pin # rel_body_edge_x: 1.8 # FH12_35: # I could not find a difference between the <=34 section and the >= 35 pin section. # series: '' # mpn_format_string: 'FH12-{pincount:d}S-0.8H' # orientation: 'H' # datasheet: 'https://www.hirose.com/product/en/products/FH12/FH12-24S-0.5SH(55)/' # pinrange: ['list', [35,36,40,45,50,53]] # text_inside_pos: 'bottom' # pitch: 0.5 # pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 # mounting_pad_size: [1.8, 2.2] # # x position mounting inner mounting pad edge relative to nearest pad center # center_pad_to_mounting_pad_edge: 1 # # y dimensions for pad given relative to mounting pad edge # rel_pad_y_outside_edge: 5 # rel_pad_y_inside_edge: 3.7 # pad_size_x: 0.3 # # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) # rel_body_edge_y: 1.9 # body_size_y: 5.6 # # body_fin_protrusion: 1.6 # # body_fin_width: 0.8 # # x body edge relative to nearest pin # rel_body_edge_x: 1.8 ================================================ FILE: scripts/Connector/Connector_SMD_single_row_plus_mounting_pad/conn_jst.yaml ================================================ group_definitions: manufacturer: 'JST' device_definition: ACH_top_entry_1: series: 'ACH' mpn_format_string: 'BM{pincount:02d}B-ACHSS-A-GAN-ETF' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eACH.pdf' pinrange: ['list', [1]] text_inside_pos: 0 pitch: 1.2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.75, 1.1] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.9 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.6 rel_pad_y_inside_edge: 3.75 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0 body_size_y: 4.3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.6 #3.2/2 edge_modifier_mount_pad_side: depth: 0.4 # > 0: cutout, < 0: protrusion width_start: 1.6 # start_from_body_side width_end: 0.8 # end_from_body_side ACH_top_entry_23: series: 'ACH' mpn_format_string: 'BM{pincount:02d}B-ACHSS-GAN-ETF' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eACH.pdf' pinrange: ['list', [2,3]] text_inside_pos: 0 pitch: 1.2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.7, 0.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.8 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.6 rel_pad_y_inside_edge: 3.75 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0 body_size_y: 4.3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 edge_modifier_mount_pad_side: depth: 0.5 # > 0: cutout, < 0: protrusion width_start: 1.8 # start_from_body_side width_end: 1 # end_from_body_side ACH_top_entry_45: series: 'ACH' mpn_format_string: 'BM{pincount:02d}B-ACHSS-A-GAN-ETF' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eACH.pdf' pinrange: ['list', [4,5]] text_inside_pos: 0 pitch: 1.2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.75, 1.1] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.8 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.6 rel_pad_y_inside_edge: 3.75 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0 body_size_y: 4.3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 edge_modifier_mount_pad_side: depth: 0.5 # > 0: cutout, < 0: protrusion width_start: 1.8 # start_from_body_side width_end: 1 # end_from_body_side AUH_top_entry: series: 'AUH' mpn_format_string: 'BM{pincount:02d}B-AUHKS-GA-TB' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eAUH.pdf' pinrange: ['list', [3,5]] text_inside_pos: 0 pitch: 1.5 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.6, 1.45] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.15 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.05 rel_pad_y_inside_edge: 4 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.3 body_size_y: 4.3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.775 edge_modifier_mount_pad_side: depth: 1 # > 0: cutout, < 0: protrusion #width_start: 1.6 start_from_body_side: 1 #width_end: 0.8 end_from_body_side: 1 LEA_top_entry: series: 'LEA' mpn_format_string: 'SM{pincount:02d}B-LEASS-TF' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eLEA.pdf' pinrange: ['list', [2]] text_inside_pos: 0 pitch: 4.2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.85, 1.75] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.15 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 6.45 rel_pad_y_inside_edge: 4.65 pad_size_x: 1.05 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.2 body_size_y: 6.3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.95 edge_modifier_mount_pad_side: depth: 0.4 # > 0: cutout, < 0: protrusion #width_start: 1.6 start_from_body_side: 1.2 #width_end: 0.8 end_from_body_side: 1.2 edge_modifier_pin_side: length: -1.6 # > 0: fin, < 0: cutout width: 1.5 GH_side_entry: series: 'GH' mpn_format_string: 'SM{pincount:02d}B-GHS-TB' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eGH.pdf' pinrange: ['range', [2, 16]] text_inside_pos: 0 pitch: 1.25 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1, 2.7] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.35 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.4 rel_pad_y_inside_edge: 3.7 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.25 body_size_y: 4.05 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 2.25 GH_top_entry: series: 'GH' mpn_format_string: 'BM{pincount:02d}B-GHS-TBT' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eGH.pdf' pinrange: ['range', [2, 16]] text_inside_pos: -1.5 pitch: 1.25 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1, 2.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.35 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.6 rel_pad_y_inside_edge: 3.9 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.3 body_size_y: 4.25 # x body edge relative to nearest pin rel_body_edge_x: 2.25 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', -0.25] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body rectangle: size: [0.5, 0.5] # centered around reference_point # start: [-0.25, -0.25] #releative to reference_point # end: [0.25, 0.25] #relative to reference_point # polygone: # - [-0.25,-0.25] # - [-0.25,0.25] # - [0.25,0.25] # - [0.25,-0.25] # - [-0.25,-0.25] repeat: spacing: ['pitch', 0] # x,y= 'pitch' | value reference_is: 'center' # 'center' | 'first' | 'last' count: 'pincount' # 'pincount' | value PH_side_entry: series: 'PH' mpn_format_string: 'S{pincount:d}B-PH-SM4-TB' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/ePH.pdf' pinrange: ['range', [2, 16]] text_inside_pos: 1.5 pitch: 2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.5, 3.4] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.6 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 9.2 rel_pad_y_inside_edge: 5.7 pad_size_x: 1 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.2 body_size_y: 6 # x body edge relative to nearest pin rel_body_edge_x: 2.95 #(7.9-2)/2 edge_modifier_pin_side: length: 1.6 # > 0: fin, < 0: cutout width: 0.8 PH_top_entry: series: 'PH' mpn_format_string: 'B{pincount:d}B-PH-SM4-TB' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/ePH.pdf' pinrange: ['range', [2, 17]] text_inside_pos: -1 pitch: 2 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.6, 3] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.6 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 6.5 rel_pad_y_inside_edge: 1 pad_size_x: 1 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 1 body_size_y: 5 # x body edge relative to nearest pin rel_body_edge_x: 2.975 #(7.95-2)/2 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', -2.5] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body rectangle: size: [0.5, 0.5] # centered around reference_point # start: [-0.25, -0.25] #releative to reference_point # end: [0.25, 0.25] #relative to reference_point # polygone: # - [-0.25,-0.25] # - [-0.25,0.25] # - [0.25,0.25] # - [0.25,-0.25] # - [-0.25,-0.25] repeat: spacing: ['pitch', 0] # x,y= 'pitch' | value reference_is: 'center' # 'center' | 'first' | 'last' count: 'pincount' # 'pincount' | value SFH_side_entry: series: 'SFH' mpn_format_string: 'SM{pincount:02}B-SFHRS-TF' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eSFH.pdf' pinrange: ['list', [2]] text_inside_pos: 0.5 pitch: 4.2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.85, 1.75] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: -0.325 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 6.45 rel_pad_y_inside_edge: 4.65 pad_size_x: 1.05 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.2 body_size_y: 5.9 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 0.5 no_automatic_silk_autline: 'True' additional_drawing: - layer: 'F.SilkS' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', 'top'] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [-1.315, -0.11] - [1.315, -0.11] - layer: 'F.SilkS' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', 'bottom'] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [-1.515, 0.11] - [1.515, 0.11] - layer: 'F.SilkS' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['left', 0] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [-0.11, -1.165] - [-0.11, 1.215] - layer: 'F.SilkS' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['right', 0] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [0.11, -1.165] - [0.11, 1.215] SHL_side_entry: series: 'SHL' mpn_format_string: 'SM{pincount:02}B-SHLS-TF' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eSHL.pdf' pinrange: ['list', [2,5,6,7,8,10,11,12,14,16,20,22,26,30]] text_inside_pos: 0.5 pitch: 1 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.9, 1.7] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.6 rel_pad_y_inside_edge: 3.35 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.7 body_size_y: 4.3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.9 SH_side_entry: series: 'SH' mpn_format_string: 'SM{pincount:02}B-SRSS-TB' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eSH.pdf' pinrange: ['list', [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20]] text_inside_pos: 0 pitch: 1 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.2, 1.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.55 rel_pad_y_inside_edge: 4 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.2 body_size_y: 4.25 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 SH_top_entry: series: 'SH' mpn_format_string: 'BM{pincount:02}B-SRSS-TB' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eSH.pdf' pinrange: ['range', [2,16]] text_inside_pos: -0.25 pitch: 1 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.2, 1.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.2 rel_pad_y_inside_edge: 2.65 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.2 body_size_y: 2.9 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', -1.25] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body rectangle: size: [0.3, 0.6] # centered around reference_point # start: [-0.25, -0.25] #releative to reference_point # end: [0.25, 0.25] #relative to reference_point # polygone: # - [-0.25,-0.25] # - [-0.25,0.25] # - [0.25,0.25] # - [0.25,-0.25] # - [-0.25,-0.25] repeat: spacing: ['pitch', 0] # x,y= 'pitch' | value reference_is: 'center' # 'center' | 'first' | 'last' count: 'pincount' # 'pincount' | value SUR_side_entry: series: 'SUR' mpn_format_string: 'SM{pincount:02}B-SURS-TF' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eSUR.pdf' pinrange: ['list', [2, 3, 4, 5, 6, 8, 10, 12, 14, 15, 16, 17, 20, 22]] text_inside_pos: 0 pitch: 0.8 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.2, 1.7] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 3.3 rel_pad_y_inside_edge: 2.3 pad_size_x: 0.5 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.35 body_size_y: 2.7 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 edge_modifier_pin_side: length: -0.3 # > 0: fin, < 0: cutout width: 0.85 SUR_top_entry: series: 'SUR' mpn_format_string: 'BM{pincount:02}B-SURS-TF' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eSUR.pdf' pinrange: ['list', [2, 3, 4, 5, 6, 8, 10, 12, 14, 15, 16, 17, 20]] text_inside_pos: -0.4 pitch: 0.8 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.2, 1.7] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 2.8 rel_pad_y_inside_edge: 1.7 pad_size_x: 0.5 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.3 body_size_y: 2 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 XAG_side_entry: series: 'XAG' mpn_format_string: 'SM{pincount:02d}B-XAGKS-BN-TB' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eXAG.pdf' pinrange: ['list', [5]] text_inside_pos: 0 pitch: 2.5 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.8, 3.9] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 4.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 12.6 rel_pad_y_inside_edge: 8.4 pad_size_x: 1.3 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.2 body_size_y: 9.5 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 6.15 edge_modifier_pin_side: length: 2.1 # > 0: fin, < 0: cutout width: 4.6 ZE_side_entry: series: 'ZE' mpn_format_string: 'SM{pincount:02}B-ZESS-TB' orientation: 'H' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eZE.pdf' pinrange: ['range', [2, 17]] text_inside_pos: 0 pitch: 1.5 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.8, 3.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 8.05 rel_pad_y_inside_edge: 5.15 pad_size_x: 0.8 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 1.45 body_size_y: 7.5 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 3 ZE_top_entry: series: 'ZE' mpn_format_string: 'BM{pincount:02}B-ZESS-TBT' orientation: 'V' datasheet: 'http://www.jst-mfg.com/product/pdf/eng/eZE.pdf' pinrange: ['range', [2, 17]] text_inside_pos: -1.5 pitch: 1.5 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.8, 3.3] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 7.9 rel_pad_y_inside_edge: 5.5 pad_size_x: 0.8 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.4 body_size_y: 5.8 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 3 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', -0.25] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body rectangle: size: [0.5, 0.5] # centered around reference_point # start: [-0.25, -0.25] #releative to reference_point # end: [0.25, 0.25] #relative to reference_point repeat: spacing: ['pitch', 0] # x,y= 'pitch' | value reference_is: 'center' # 'center' | 'first' | 'last' count: 'pincount' # 'pincount' | value ================================================ FILE: scripts/Connector/Connector_SMD_single_row_plus_mounting_pad/conn_molex.yaml ================================================ group_definitions: manufacturer: 'Molex' device_definition: Panelmate_side_entry: series: 'Panelmate' mpn_format_string: '53780-{pincount:02d}70' orientation: 'H' datasheet: '' pinrange: ['list', [2,3,4,5,6,7,8,9,10,12,14,15,18,30]] text_inside_pos: 'center' pitch: 1.25 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.3, 3.35] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 2.2 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 7.5 rel_pad_y_inside_edge: 5.6 pad_size_x: 0.8 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.1 body_size_y: 5.9 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 3.2 edge_modifier_mount_pad_side: depth: 1 # > 0: cutout, < 0: protrusion # width_start: 1.6 start_from_body_side: 1.9 # width_end: 0.8 end_from_body_side: 2.3 PicoEZ_top_entry: series: 'Pico-EZmate' mpn_format_string: '78171-00{pincount:02d}' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/781710002_sd.pdf' pinrange: ['list', [2,3,4,5]] text_inside_pos: 'center' pitch: 1.2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.7, 0.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.8 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.6 rel_pad_y_inside_edge: 3.75 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.22 body_size_y: 4.5 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 edge_modifier_mount_pad_side: depth: 0.5 # > 0: cutout, < 0: protrusion # width_start: 1.6 start_from_body_side: 1.35 # width_end: 0.8 end_from_body_side: 1.65 PicoEZSlim_top_entry: series: 'Pico-EZmate_Slim' mpn_format_string: '202656-0{pincount:02d}1' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/2026560021_sd.pdf' pinrange: ['list', [2]] text_inside_pos: 'center' pitch: 1.2 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [0.7, 0.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.95 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.85 rel_pad_y_inside_edge: 4 pad_size_x: 0.7 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.18 body_size_y: 4.72 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.65 edge_modifier_mount_pad_side: depth: 0.8 # > 0: cutout, < 0: protrusion width_start: 2.3 #start_from_body_side: 1.35 width_end: 2.3 #end_from_body_side: 1.65 PicoBlade_top_entry: series: 'PicoBlade' mpn_format_string: '53398-{pincount:02d}71' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/533980271_sd.pdf' pinrange: ['range', [2,16]] text_inside_pos: 0.4 pitch: 1.25 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [2.1, 3] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.5 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.9 rel_pad_y_inside_edge: 3.6 pad_size_x: 0.8 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.4 body_size_y: 3.7 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 # amount to shift y position of center for pick-and-place (positive -> shift whole footprint up) center_shift_y: -0.55 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', 1.525] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body rectangle: size: [0.3, 0.6] # centered around reference_point # start: [-0.25, -0.25] #releative to reference_point # end: [0.25, 0.25] #relative to reference_point repeat: spacing: ['pitch', 0] # x,y= 'pitch' | value reference_is: 'center' # 'center' | 'first' | 'last' count: 'pincount' # 'pincount' | value - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['left', 'bottom'] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [0, 0] - [-1.5, 0] - [-1.7, -0.2] - [-1.7, -2.0] - [-1.5, -2.2] - [-1.5, -2.8] - [0, -2.8] - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['right', 'bottom'] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [0, 0] - [1.5, 0] - [1.7, -0.2] - [1.7, -2.0] - [1.5, -2.2] - [1.5, -2.8] - [0, -2.8] PicoBlade_side_entry: series: 'PicoBlade' mpn_format_string: '53261-{pincount:02d}71' orientation: 'H' datasheet: 'http://www.molex.com/pdm_docs/sd/532610271_sd.pdf' pinrange: ['list', [2,3,4,5,6,7,8,9,10,11,12,13,14,15,17]] text_inside_pos: 'bottom' pitch: 1.25 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [2.1, 3] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.5 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.2 rel_pad_y_inside_edge: 3.6 pad_size_x: 0.8 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.6 body_size_y: 4.2 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 # amount to shift y position of center for pick-and-place (positive -> shift whole footprint up) center_shift_y: 0.6 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['left', 'top'] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [0, 1] - [-1.5, 1] - [-1.7, 1.2] - [-1.7, 3.0] - [-1.5, 3.2] - [-1.5, 3.8] - [0, 3.8] - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['right', 'top'] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body polygone: - [0, 1] - [1.5, 1] - [1.7, 1.2] - [1.7, 3.0] - [1.5, 3.2] - [1.5, 3.8] - [0, 3.8] PicoClasp_top_entry_1: series: 'Pico-Clasp' mpn_format_string: '501331-{pincount:02d}07' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/5013310207_sd.pdf' pinrange: ['range', [2,6]] text_inside_pos: 'top' pitch: 1 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.2, 1.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.2 rel_pad_y_inside_edge: 2.65 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.25 body_size_y: 3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', 0] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body rectangle: size: [0.25, 0.5] # centered around reference_point # start: [-0.25, -0.25] #releative to reference_point # end: [0.25, 0.25] #relative to reference_point repeat: spacing: ['pitch', 0] # x,y= 'pitch' | value reference_is: 'center' # 'center' | 'first' | 'last' count: 'pincount' # 'pincount' | value PicoClasp_top_entry_2: series: 'Pico-Clasp' mpn_format_string: '501331-{pincount:02d}07' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/5013310207_sd.pdf' pinrange: ['range', [6,16]] text_inside_pos: 'top' pitch: 1 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.2, 1.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 4.2 rel_pad_y_inside_edge: 2.65 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -0.25 body_size_y: 3 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 edge_modifier_mount_pad_side: depth: -1.47 # > 0: cutout, < 0: protrusion width_start: 4.5 #start_from_body_side: 1.9 width_end: 4.5 #end_from_body_side: 2.3 additional_drawing: - layer: 'F.Fab' # thickness: 0.1 #optional parameter. If not given: take fab_line_width and silk_line_width from config file. Needed if layer not silk or fab! reference_point: ['center', 0] # [x,y]: x = 'left' | 'center' | 'right' | value; y = 'top' | 'center' | 'bottom' | value; named values are relative to body rectangle: size: [0.25, 0.5] # centered around reference_point # start: [-0.25, -0.25] #releative to reference_point # end: [0.25, 0.25] #relative to reference_point repeat: spacing: ['pitch', 0] # x,y= 'pitch' | value reference_is: 'center' # 'center' | 'first' | 'last' count: 'pincount' # 'pincount' | value PicoClasp_side_entry: series: 'Pico-Clasp' mpn_format_string: '202396-{pincount:02d}07' orientation: 'H' datasheet: 'http://www.molex.com/pdm_docs/sd/2023960207_sd.pdf' pinrange: ['range', [2,16]] text_inside_pos: 'bottom' pitch: 1 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.2, 1.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 0.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.55 rel_pad_y_inside_edge: 4.05 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.7 body_size_y: 5.35 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 1.5 PicoLock_side_entry: series: 'Pico-Lock' mpn_format_string: '504050-{pincount:02d}91' orientation: 'H' datasheet: 'http://www.molex.com/pdm_docs/sd/5040500891_sd.pdf' pinrange: ['list', [4,5,6,7,8,10,12]] text_inside_pos: 'center' pitch: 1.5 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.25, 1.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.98 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 6.59 rel_pad_y_inside_edge: 5.59 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.02 body_size_y: 6.1 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 2.625 edge_modifier_mount_pad_side: depth: 2 # > 0: cutout, < 0: protrusion #width_start: 4.5 start_from_body_side: 1.95 #width_end: 4.5 end_from_body_side: 1.95 CLIKmate_top_entry: series: 'CLIK-Mate' mpn_format_string: '502382-{pincount:02d}70' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/5023820270_sd.pdf' pinrange: ['range', [2,16]] text_inside_pos: 'center' pitch: 1.25 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1, 2.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.35 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.6 rel_pad_y_inside_edge: 3.9 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.7 body_size_y: 5.45 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 2.3 CLIKmate_top_entry_15: series: 'CLIK-Mate' mpn_format_string: '505405-{pincount:02d}70' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/5054050270_sd.pdf' pinrange: ['range', [2,16]] text_inside_pos: 'center' pitch: 1.5 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.8, 3.3] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 7.9 rel_pad_y_inside_edge: 5.5 pad_size_x: 0.8 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.27 body_size_y: 6.35 # x body edge relative to nearest pin rel_body_edge_x: 2.9 CLIKmate_top_entry_20: series: 'CLIK-Mate' mpn_format_string: '502443-{pincount:02d}70' orientation: 'V' datasheet: 'http://www.molex.com/pdm_docs/sd/5024430270_sd.pdf' pinrange: ['list', [2,3,4,5,6,7,8,9,12,13,14,15]] text_inside_pos: 'center' pitch: 2.0 pad1_position: 'bottom-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.8, 3.6] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.45 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 7.9 rel_pad_y_inside_edge: 5.0 pad_size_x: 1.0 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: 0.45 body_size_y: 6.85 # x body edge relative to nearest pin rel_body_edge_x: 3.0 CLIKmate_side_entry: series: 'CLIK-Mate' mpn_format_string: '502386-{pincount:02d}70' orientation: 'H' datasheet: 'http://www.molex.com/pdm_docs/sd/5023860270_sd.pdf' pinrange: ['range', [2,16]] text_inside_pos: 'center' pitch: 1.25 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1, 2.7] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.35 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 5.4 rel_pad_y_inside_edge: 3.7 pad_size_x: 0.6 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -1.35 body_size_y: 3.15 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 2.3 edge_modifier_mount_pad_side: depth: -1.25 # > 0: cutout, < 0: protrusion #width_start: 4.5 start_from_body_side: 0.33 #width_end: 4.5 end_from_body_side: 0.33 CLIKmate_side_entry_15: series: 'CLIK-Mate' mpn_format_string: '502585-{pincount:02d}70' orientation: 'H' datasheet: 'http://www.molex.com/pdm_docs/sd/5025850270_sd.pdf' pinrange: ['range', [2,16]] text_inside_pos: 'center' pitch: 1.5 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.8, 3.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.7 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 8.05 rel_pad_y_inside_edge: 5.15 pad_size_x: 0.8 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -1.35 body_size_y: 4.35 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 2.9 edge_modifier_mount_pad_side: depth: -2.6 # > 0: cutout, < 0: protrusion start_from_body_side: 0.33 end_from_body_side: 0.33 CLIKmate_side_entry_20: series: 'CLIK-Mate' mpn_format_string: '502494-{pincount:02d}70' orientation: 'H' datasheet: 'http://www.molex.com/pdm_docs/sd/5024940270_sd.pdf' pinrange: ['list', [2,3,4,6,8,10,12,13,14,15]] text_inside_pos: 'center' pitch: 2.0 pad1_position: 'top-left' # 'top-left' | 'bottom-left' -> pin 2 always to the right of pin 1 mounting_pad_size: [1.8, 3.8] # x position mounting inner mounting pad edge relative to nearest pad center center_pad_to_mounting_pad_edge: 1.45 # y dimensions for pad given relative to mounting pad edge rel_pad_y_outside_edge: 7.7 rel_pad_y_inside_edge: 5.0 pad_size_x: 1.0 # y position for body edge relative to mounting pad edge (positive -> body extends outside bounding box) rel_body_edge_y: -1.3 body_size_y: 4.35 # body_fin_protrusion: 1.6 # body_fin_width: 0.8 # x body edge relative to nearest pin rel_body_edge_x: 3.0 edge_modifier_mount_pad_side: depth: -2.6 # > 0: cutout, < 0: protrusion start_from_body_side: 0.33 end_from_body_side: 0.33 ================================================ FILE: scripts/Connector/Connector_SMD_single_row_plus_mounting_pad/helpers.py ================================================ from KicadModTree import * def roundToBase(value, base): return round(value/base) * base def parseAdditionalDrawing(footprint, drawing_definition, configuration, series_definition, body_edges, pincount): ref = drawing_definition.get('reference_point', ['center','center']).copy() if ref[0] == 'left': ref[0] = body_edges['left'] elif ref[0] == 'center': ref[0] = (body_edges['left'] + body_edges['right'])/2 elif ref[0] == 'right': ref[0] = body_edges['right'] if ref[1] == 'top': ref[1] = body_edges['top'] elif ref[1] == 'center': ref[1] = (body_edges['top'] + body_edges['bottom'])/2 elif ref[1] == 'bottom': ref[1] = body_edges['bottom'] if 'rectangle' in drawing_definition: if 'size' in drawing_definition['rectangle']: size = drawing_definition['rectangle']['size'] start = [ref[0] - size[0]/2, ref[1] - size[1]/2] end = [ref[0] + size[0]/2, ref[1] + size[1]/2] elif 'start' in drawing_definition['rectangle'] and 'end' in drawing_definition['rectangle']: start = drawing_definition['rectangle']['start'] start = [ref[0] + start[0], ref[1] + start[1]] end = drawing_definition['rectangle']['end'] end = [ref[0] + end[0], ref[1] + end[1]] else: print('rectangle without size size defintion found. Ignored') return elif 'polygone' in drawing_definition: # ToDo: implement polygone = [] for point in drawing_definition['polygone']: polygone.append({'x':ref[0]+point[0], 'y':ref[1]+point[1]}) else: # not implemented. return #print(polygone) layer=drawing_definition.get('layer', 'F.Fab') if 'thickness' in drawing_definition: thickness = drawing_definition['thickness'] elif 'Fab' in layer: thickness = configuration['fab_line_width'] elif 'SilkS' in layer: thickness = configuration['silk_line_width'] else: print('drawing not on silk or fab but no line thickness given.') return if 'repeat' in drawing_definition: repeat_def = drawing_definition['repeat'] spacing = repeat_def['spacing'] if spacing[0] == 'pitch': spacing[0] = series_definition['pitch'] if spacing[1] == 'pitch': spacing[1] = series_definition['pitch'] count = repeat_def['count'] if count == 'pincount': count = pincount first = ref.copy() if repeat_def['reference_is'] == 'last': first[0] = (count-1)*spacing[0] first[1] = (count-1)*spacing[1] spacing[0] *= -1 spacing[1] *= -1 elif repeat_def['reference_is'] == 'center': first[0] = -(count-1)*spacing[0]/2 first[1] = -(count-1)*spacing[1]/2 for i in range(count): translation = Translation(first[0]+i*spacing[0], first[1]+i*spacing[1]) if 'rectangle' in drawing_definition: translation.append(RectLine(start=start, end=end, layer=layer, width=thickness)) elif 'polygone' in drawing_definition: translation.append(PolygoneLine(polygone=polygone, layer=layer, width=thickness)) footprint.append(translation) else: if 'rectangle' in drawing_definition: footprint.append(RectLine(start=start, end=end, layer=layer, width=thickness)) elif 'polygone' in drawing_definition: #print(polygone) footprint.append(PolygoneLine(polygone=polygone, layer=layer, width=thickness)) ================================================ FILE: scripts/Connector/Connector_SMD_single_row_plus_mounting_pad/smd_single_row_plus_mounting_pad.py ================================================ #!/usr/bin/env python3 # Generator for jst smd connectors (single row with two mounting pads) import sys import os # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * from math import sqrt sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields def generate_one_footprint(idx, pincount, series_definition, configuration, group_definition): if 'mpn_param_1' in series_definition: mpn_param_1 = series_definition['mpn_param_1'] mpn = series_definition['mpn_format_string'].format(pincount=pincount, param_1=mpn_param_1[idx]) else: mpn = series_definition['mpn_format_string'].format(pincount=pincount) pins_toward_bottom = series_definition['pad1_position'] == 'bottom-left' needs_additional_silk_pin1_marker = False pad_size = [series_definition['pad_size_x'], series_definition['rel_pad_y_outside_edge'] - series_definition['rel_pad_y_inside_edge']] pad_pos_y = -series_definition['rel_pad_y_outside_edge']/2 + pad_size[1]/2 mounting_pad_size = series_definition['mounting_pad_size'] mount_pad_y_pos = series_definition['rel_pad_y_outside_edge']/2 - mounting_pad_size[1]/2 if 'center_shift_y' in series_definition: mount_pad_y_pos -= series_definition['center_shift_y'] pad_pos_y -= series_definition['center_shift_y'] mount_pad_center_x_to_pin = series_definition['center_pad_to_mounting_pad_edge'] + mounting_pad_size[0]/2.0 # center pin 1 to center pin n dimension_A = (pincount-1)*series_definition['pitch'] body_edge = {} if pins_toward_bottom: pad_pos_y *= -1 mount_pad_y_pos *= -1 mount_pad_edge_y_outside = mount_pad_y_pos - mounting_pad_size[1]/2 body_edge['top'] = mount_pad_edge_y_outside - series_definition['rel_body_edge_y'] body_edge['bottom'] = body_edge['top'] + series_definition['body_size_y'] else: mount_pad_edge_y_outside = mount_pad_y_pos + mounting_pad_size[1]/2 body_edge['bottom'] = mount_pad_edge_y_outside + series_definition['rel_body_edge_y'] body_edge['top'] = body_edge['bottom'] - series_definition['body_size_y'] body_edge['right'] = dimension_A/2 + series_definition['rel_body_edge_x'] body_edge['left'] = -body_edge['right'] orientation = configuration['orientation_options'][series_definition['orientation']] footprint_name = configuration['fp_name_format_string'].format(man=group_definition['manufacturer'], series=series_definition['series'], mpn=mpn, num_rows=1, pins_per_row=pincount, mounting_pad = "-1MP", pitch=series_definition['pitch'], orientation=orientation) footprint_name = footprint_name.replace('__', '_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{:s} {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(group_definition['manufacturer'], series_definition['series'], mpn, series_definition['datasheet'])) kicad_mod.setAttribute('smd') kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series_definition['series'], orientation=orientation, man=group_definition['manufacturer'], entry=configuration['entry_direction'][series_definition['orientation']])) ############################# Pads ################################## optional_pad_params = {} if configuration['kicad4_compatible']: pad_shape=Pad.SHAPE_RECT else: pad_shape=Pad.SHAPE_ROUNDRECT optional_pad_params['radius_ratio'] = configuration.get('radius_ratio', 0.25) optional_pad_params['maximum_radius'] = configuration.get('maximum_radius', 0.25) kicad_mod.append(PadArray( center=[0, pad_pos_y], x_spacing=series_definition['pitch'], pincount=pincount, size=pad_size, type=Pad.TYPE_SMT, shape=pad_shape, layers=Pad.LAYERS_SMT, **optional_pad_params)) mount_pad_left_x_pos = -dimension_A/2 - mount_pad_center_x_to_pin kicad_mod.append(Pad( number = configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=pad_shape, at=[mount_pad_left_x_pos, mount_pad_y_pos], size=mounting_pad_size, layers=Pad.LAYERS_SMT, **optional_pad_params)) kicad_mod.append(Pad( number = configuration['mounting_pad_number'], type=Pad.TYPE_SMT, shape=pad_shape, at=[-mount_pad_left_x_pos, mount_pad_y_pos], size=mounting_pad_size, layers=Pad.LAYERS_SMT, **optional_pad_params)) ######################### Body outline ############################### pad_edge_silk_center_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 pad_1_x_outside_edge = -dimension_A/2 - pad_size[0]/2 if pins_toward_bottom: #Man i wish there where a rotate footprint function available. body_edge_pin = body_edge['bottom'] body_edge_mount_pad = body_edge['top'] silk_y_mp_pin_side = mount_pad_y_pos + mounting_pad_size[1]/2 + pad_edge_silk_center_offset mp_edge_outside = mount_pad_y_pos - mounting_pad_size[1]/2 silk_y_mp_outside = mp_edge_outside - pad_edge_silk_center_offset pin_edge_outside = pad_pos_y + pad_size[1]/2 silk_y_offset_pin_side = configuration['silk_fab_offset'] else: body_edge_pin = body_edge['top'] body_edge_mount_pad = body_edge['bottom'] silk_y_mp_pin_side = mount_pad_y_pos - mounting_pad_size[1]/2 - pad_edge_silk_center_offset mp_edge_outside = mount_pad_y_pos + mounting_pad_size[1]/2 silk_y_mp_outside = mp_edge_outside + pad_edge_silk_center_offset pin_edge_outside = pad_pos_y - pad_size[1]/2 silk_y_offset_pin_side = -configuration['silk_fab_offset'] # Pin side bounding_box_y_pin_side = pad_pos_y + (pad_size[1]/2 if pins_toward_bottom else -pad_size[1]/2) side_line_y_pin_side = body_edge_pin mp_inner_edge_x_left_silk = mount_pad_left_x_pos + mounting_pad_size[0]/2 + pad_edge_silk_center_offset modified_pinside_x_inner = body_edge['left'] if 'edge_modifier_pin_side' in series_definition: modifier = series_definition['edge_modifier_pin_side'] modified_pinside_x_inner = body_edge['left'] + modifier['width'] if pins_toward_bottom: side_line_y_pin_side += modifier['length'] if side_line_y_pin_side > bounding_box_y_pin_side: bounding_box_y_pin_side = side_line_y_pin_side else: side_line_y_pin_side -= modifier['length'] if side_line_y_pin_side < bounding_box_y_pin_side: bounding_box_y_pin_side = side_line_y_pin_side poly_fab_pin_side=[ {'x': body_edge['left'], 'y': side_line_y_pin_side}, {'x': modified_pinside_x_inner, 'y': side_line_y_pin_side}, {'x': modified_pinside_x_inner, 'y': body_edge_pin}, {'x': -modified_pinside_x_inner, 'y': body_edge_pin}, {'x': -modified_pinside_x_inner, 'y': side_line_y_pin_side}, {'x': body_edge['right'], 'y': side_line_y_pin_side} ] if modifier['length'] < 0: silk_x_offset = -configuration['silk_fab_offset'] else: silk_x_offset = configuration['silk_fab_offset'] if modified_pinside_x_inner + silk_x_offset > pad_1_x_outside_edge - pad_edge_silk_center_offset: poly_silk_edge_left = [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': pin_edge_outside} ] if abs(pin_edge_outside) - abs(side_line_y_pin_side + silk_y_offset_pin_side) < configuration['silk_line_lenght_min']: needs_additional_silk_pin1_marker = True poly_silk_edge_right = [ {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': -pad_1_x_outside_edge + pad_edge_silk_center_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side} ] else: poly_silk_edge_left = [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': modified_pinside_x_inner + silk_x_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': modified_pinside_x_inner + silk_x_offset, 'y': body_edge_pin + silk_y_offset_pin_side}, {'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side}, {'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': pin_edge_outside} ] if abs(pin_edge_outside) - abs(body_edge_pin + silk_y_offset_pin_side) < configuration['silk_line_lenght_min']: needs_additional_silk_pin1_marker = True poly_silk_edge_right = [ {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': -modified_pinside_x_inner - silk_x_offset, 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': -modified_pinside_x_inner - silk_x_offset, 'y': body_edge_pin + silk_y_offset_pin_side}, {'x': -pad_1_x_outside_edge + pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side} ] else: poly_fab_pin_side=[ {'x': body_edge['left'], 'y': body_edge_pin}, {'x': body_edge['right'], 'y': body_edge_pin} ] poly_silk_edge_left = [ {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side}, {'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side}, {'x': pad_1_x_outside_edge - pad_edge_silk_center_offset, 'y': pin_edge_outside} ] if abs(pin_edge_outside) - abs(body_edge_pin + silk_y_offset_pin_side) < configuration['silk_line_lenght_min']: needs_additional_silk_pin1_marker = True poly_silk_edge_right = [ {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_pin_side}, {'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': side_line_y_pin_side + silk_y_offset_pin_side}, {'x': -pad_1_x_outside_edge + pad_edge_silk_center_offset, 'y': body_edge_pin + silk_y_offset_pin_side} ] kicad_mod.append(PolygoneLine(polygone=poly_fab_pin_side, layer='F.Fab', width=configuration['fab_line_width'])) if series_definition.get('no_automatic_silk_autline','False') != 'True': kicad_mod.append(PolygoneLine(polygone=poly_silk_edge_left, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_edge_right, layer='F.SilkS', width=configuration['silk_line_width'])) # Mount pad side bounding_box_y_mount_pad_side = mount_pad_y_pos + (-mounting_pad_size[1]/2 if pins_toward_bottom else mounting_pad_size[1]/2) if abs(bounding_box_y_mount_pad_side) < abs(body_edge_mount_pad): bounding_box_y_mount_pad_side = body_edge_mount_pad mid_line_y_mount_pad_side = body_edge_mount_pad if 'edge_modifier_mount_pad_side' in series_definition: modifier = series_definition['edge_modifier_mount_pad_side'] if 'width_start' in modifier: modified_mp_start_x_inner = - modifier['width_start']/2 # We assume centered body! if 'start_from_body_side' in modifier: modified_mp_start_x_inner = body_edge['left'] + modifier['start_from_body_side'] modified_mp_end_x_inner = modified_mp_start_x_inner if 'width_end' in modifier: modified_mp_end_x_inner = - modifier['width_end']/2 # We assume centered body! if 'end_from_body_side' in modifier: modified_mp_end_x_inner = body_edge['left'] + modifier['end_from_body_side'] if pins_toward_bottom: mid_line_y_mount_pad_side += modifier['depth'] if mid_line_y_mount_pad_side < bounding_box_y_mount_pad_side: bounding_box_y_mount_pad_side = mid_line_y_mount_pad_side else: mid_line_y_mount_pad_side -= modifier['depth'] if mid_line_y_mount_pad_side > bounding_box_y_mount_pad_side: bounding_box_y_mount_pad_side = mid_line_y_mount_pad_side if modifier['depth'] < 0: silk_x_offset = -configuration['silk_fab_offset'] else: silk_x_offset = configuration['silk_fab_offset'] poly_fab_mp_side=[ {'x': body_edge['left'], 'y': body_edge_mount_pad}, {'x': modified_mp_start_x_inner, 'y': body_edge_mount_pad}, {'x': modified_mp_end_x_inner, 'y': mid_line_y_mount_pad_side}, {'x': -modified_mp_end_x_inner, 'y': mid_line_y_mount_pad_side}, {'x': -modified_mp_start_x_inner, 'y': body_edge_mount_pad}, {'x': body_edge['right'], 'y': body_edge_mount_pad} ] poly_silk_mp_side=[ {'x': mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side}, {'x': modified_mp_start_x_inner + silk_x_offset, 'y': body_edge_mount_pad - silk_y_offset_pin_side}, {'x': modified_mp_end_x_inner + silk_x_offset, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side}, {'x': -modified_mp_end_x_inner - silk_x_offset, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side}, {'x': -modified_mp_start_x_inner - silk_x_offset, 'y': body_edge_mount_pad - silk_y_offset_pin_side}, {'x': -mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side} ] if modified_mp_start_x_inner + configuration['silk_fab_offset'] < mp_inner_edge_x_left_silk: poly_silk_mp_side=[ {'x': mp_inner_edge_x_left_silk, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side}, {'x': -mp_inner_edge_x_left_silk, 'y': mid_line_y_mount_pad_side - silk_y_offset_pin_side} ] else: poly_fab_mp_side=[ {'x': body_edge['left'], 'y': body_edge_mount_pad}, {'x': body_edge['right'], 'y': body_edge_mount_pad} ] poly_silk_mp_side=[ {'x': mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side}, {'x': -mp_inner_edge_x_left_silk, 'y': body_edge_mount_pad - silk_y_offset_pin_side} ] if series_definition['rel_body_edge_y'] > pad_edge_silk_center_offset: poly_silk_mp_side[0]['x'] = body_edge['left'] poly_silk_mp_side[len(poly_silk_mp_side)-1]['x'] = body_edge['right'] if series_definition['rel_body_edge_y'] > pad_edge_silk_center_offset + configuration['silk_line_lenght_min']: poly_silk_mp_side[0]['x'] = body_edge['left'] - configuration['silk_fab_offset'] poly_silk_mp_side[len(poly_silk_mp_side)-1]['x'] = body_edge['right'] + configuration['silk_fab_offset'] poly_silk_mp_side.insert(0,{'x': body_edge['left'] - configuration['silk_fab_offset'], 'y': silk_y_mp_outside}) poly_silk_mp_side.append({'x': body_edge['right'] + configuration['silk_fab_offset'], 'y': silk_y_mp_outside}) if series_definition.get('no_automatic_silk_autline','False') != 'True': kicad_mod.append(PolygoneLine(polygone=poly_silk_mp_side, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_fab_mp_side, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[body_edge['left'], side_line_y_pin_side], end=[body_edge['left'], body_edge_mount_pad], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Line(start=[body_edge['right'], side_line_y_pin_side], end=[body_edge['right'], body_edge_mount_pad], layer='F.Fab', width=configuration['fab_line_width'])) ###################### Additional Drawing ########################### if 'additional_drawing' in series_definition: for drawing in series_definition['additional_drawing']: parseAdditionalDrawing(kicad_mod, drawing, configuration, series_definition, body_edge, pincount) ############################# CrtYd ################################## mp_left_edge = mount_pad_left_x_pos - mounting_pad_size[0]/2 bounding_box_x1 = body_edge['left'] if body_edge['left'] < mp_left_edge else mp_left_edge bounding_box_x2 = -bounding_box_x1 if pins_toward_bottom: bounding_box_y1 = bounding_box_y_mount_pad_side bounding_box_y2 = bounding_box_y_pin_side else: bounding_box_y1 = bounding_box_y_pin_side bounding_box_y2 = bounding_box_y_mount_pad_side cx1 = roundToBase(bounding_box_x1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box_x2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box_y1 - configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box_y2 + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Pin 1 marker ############################## if series_definition['pad1_position'] == 'bottom-left': poly_pin1_marker = [ {'x':-dimension_A/2 - configuration['fab_pin1_marker_length']/2,'y': body_edge['bottom']}, {'x':-dimension_A/2,'y': body_edge['bottom'] - configuration['fab_pin1_marker_length']/sqrt(2)}, {'x':-dimension_A/2 + configuration['fab_pin1_marker_length']/2,'y': body_edge['bottom']} ] poly_pin1_marker_small = [ {'x':-dimension_A/2-configuration['fab_pin1_marker_length']/4,'y': cy2 + configuration['fab_pin1_marker_length']/sqrt(8)}, {'x':-dimension_A/2,'y': cy2}, {'x':-dimension_A/2+configuration['fab_pin1_marker_length']/4,'y': cy2 + configuration['fab_pin1_marker_length']/sqrt(8)}, {'x':-dimension_A/2-configuration['fab_pin1_marker_length']/4,'y': cy2 + configuration['fab_pin1_marker_length']/sqrt(8)} ] else: poly_pin1_marker = [ {'x':-dimension_A/2 - configuration['fab_pin1_marker_length']/2,'y': body_edge['top']}, {'x':-dimension_A/2,'y': body_edge['top'] + configuration['fab_pin1_marker_length']/sqrt(2)}, {'x':-dimension_A/2 + configuration['fab_pin1_marker_length']/2,'y': body_edge['top']} ] poly_pin1_marker_small = [ {'x':-dimension_A/2-configuration['fab_pin1_marker_length']/4,'y': cy1 - configuration['fab_pin1_marker_length']/sqrt(8)}, {'x':-dimension_A/2,'y': cy1}, {'x':-dimension_A/2+configuration['fab_pin1_marker_length']/4,'y': cy1 - configuration['fab_pin1_marker_length']/sqrt(8)}, {'x':-dimension_A/2-configuration['fab_pin1_marker_length']/4,'y': cy1 - configuration['fab_pin1_marker_length']/sqrt(8)} ] if modified_pinside_x_inner < -dimension_A/2 - configuration['fab_pin1_marker_length']/2: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) else: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_small, layer='F.Fab', width=configuration['fab_line_width'])) if needs_additional_silk_pin1_marker: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_small, layer='F.SilkS', width=configuration['silk_line_width'])) ######################### Text Fields ############################### text_center = series_definition.get('text_inside_pos', 'center') addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center) ########################### file names ############################### model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(man=group_definition['manufacturer'], series=series_definition['series']) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) def generate_series(configuration, series_definition, id, group_definition): idx = 0 pinrange_def_type, pinrange_def = series_definition['pinrange'] if pinrange_def_type == 'range': pinrange = range(*pinrange_def) elif pinrange_def_type == 'list': pinrange = pinrange_def else: print("Pinrange definition error in part {:s}".format(id)) return for pincount in pinrange: generate_one_footprint(idx, pincount, series_definition, configuration, group_definition) idx += 1 if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('files', metavar='file', type=str, nargs='+', help='list of files holding information about what devices should be created.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for filepath in args.files: with open(filepath, 'r') as stream: try: yaml_file = yaml.safe_load(stream) except yaml.YAMLError as exc: print(exc) series_definitions = yaml_file['device_definition'] for series_definition_id in series_definitions: generate_series(configuration, series_definitions[series_definition_id], series_definition_id, yaml_file['group_definitions']) ================================================ FILE: scripts/Connector/Connector_Samtec/conn_samtec_LSHM_smd_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "" series_long = 'LSHM 0.50 mm Razor Beam High-Speed Hermaphroditic Terminal/Socket Strip' manufacturer = 'Samtec' orientation = 'V' number_of_rows = 2 datasheet = 'http://suddendocs.samtec.com/prints/lshm-1xx-xx.x-x-dv-a-x-x-tr-footprint.pdf' #pins_per_row per row pins_per_row_range = [5,10,20,30,40,50] #Molex part number #n = number of circuits per row part_code = "LSHM-1{n:02d}-xx.x-x-DV-{shield:s}" variant_params = { 'shileded': { 'mpn_option': 'S', 'shield_pad': True, }, 'plain': { 'mpn_option': 'N', 'shield_pad': False, } } pitch = 0.5 pad_size = [0.3, 1.5] boss_drill = 1.45 shield_pad_drill = 1 shield_pad_size = 1.5 pin_number_shield = "SH" def generate_one_footprint(pins_per_row, params, configuration): mpn = part_code.format(n=pins_per_row, shield=params['mpn_option']) CrtYd_off = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] off = configuration['silk_fab_offset'] pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 body_edge = {} bounding_box = {} # handle arguments orientation_str = configuration['orientation_options'][orientation] if params['shield_pad']: footprint_name = configuration['fp_name_format_string_shielded'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, pitch=pitch, orientation=orientation_str, shield_pins=1) else: footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace('__','_') kicad_mod = Footprint(footprint_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Molex {:s}, {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator".format(series_long, mpn, pins_per_row, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) A = (pins_per_row-1)*pitch B = A + 2.5 C = A + 5.45 D = A + 6.75 E = A + 5.2 pad_to_pad_inside = 1.95+0.25 pad_y = (pad_to_pad_inside + pad_size[1])/2 boss_x = B/2 boss_y = -pad_y + pad_size[1]/2 + 0.25 shield_pad_x = C/2 shield_pad_y = boss_y + 2 body_chamfer = 0.3 body_edge['left'] = -D/2 if params['shield_pad'] else -E/2 body_edge['right'] = -body_edge['left'] body_edge['top'] = -4.98/2 body_edge['bottom'] = -body_edge['top'] bounding_box['left'] = (-shield_pad_x - shield_pad_size/2) if params['shield_pad'] else body_edge['left'] bounding_box['right'] = -bounding_box['left'] bounding_box['top'] = -pad_y - pad_size[1]/2 bounding_box['bottom'] = -bounding_box['top'] ################################ Pads ##################################### kicad_mod.append(PadArray(initial=1, increment=2, center=[0, -pad_y], x_spacing=pitch, pincount=pins_per_row, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(PadArray(initial=2, increment=2, center=[0, pad_y], x_spacing=pitch, pincount=pins_per_row, size=pad_size, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number ='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(number ='""', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[-boss_x, boss_y], size=boss_drill, drill=boss_drill, layers=Pad.LAYERS_NPTH)) if params['shield_pad']: kicad_mod.append(Pad(number = pin_number_shield, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[shield_pad_x, shield_pad_y], size=shield_pad_size, drill=shield_pad_drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number = pin_number_shield, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[-shield_pad_x, shield_pad_y], size=shield_pad_size, drill=shield_pad_drill, layers=Pad.LAYERS_THT)) ########################### Outline ################################ poly_fab = [ {'x': 0, 'y': body_edge['top']}, {'x': body_edge['left']+body_chamfer, 'y': body_edge['top']}, {'x': body_edge['left'], 'y': body_edge['top']+body_chamfer}, {'x': body_edge['left'], 'y': body_edge['bottom']-body_chamfer}, {'x': body_edge['left']+body_chamfer, 'y': body_edge['bottom']}, {'x': 0, 'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=poly_fab, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_fab, x_mirror=0, layer='F.Fab', width=configuration['fab_line_width'])) pad_x_outside_edge = A/2 + pad_size[0]/2 + pad_silk_off if not params['shield_pad']: poly_silk = [ {'x': -pad_x_outside_edge, 'y': body_edge['top']-off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']+body_chamfer-off}, {'x': body_edge['left']-off, 'y': body_edge['bottom']-body_chamfer+off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['bottom']+off}, {'x': -pad_x_outside_edge, 'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=poly_silk, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) else: r = (shield_pad_size/2 + pad_silk_off) x = (D-C)/2 dy = sqrt(r**2 - x**2) poly_silk_top = [ {'x': -pad_x_outside_edge, 'y': body_edge['top']-off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']+body_chamfer-off}, {'x': body_edge['left']-off, 'y': shield_pad_y-dy}, ] kicad_mod.append(PolygoneLine(polygone=poly_silk_top, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_top, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) poly_silk_bottom = [ {'x': body_edge['left']-off, 'y': shield_pad_y+dy}, {'x': body_edge['left']-off, 'y': body_edge['bottom']-body_chamfer+off}, {'x': body_edge['left']+body_chamfer-off, 'y': body_edge['bottom']+off}, {'x': -pad_x_outside_edge, 'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_bottom, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=poly_silk_bottom, x_mirror=0, layer='F.SilkS', width=configuration['silk_line_width'])) ########################### Pin 1 ################################# p1s_sl = 0.4 p1s_y = -pad_y - pad_size[1]/2 - pad_silk_off p1_x = -A/2 p1s_poly = [ {'x': p1_x, 'y':p1s_y}, {'x': p1_x-p1s_sl/2, 'y':p1s_y-p1s_sl/sqrt(2)}, {'x': p1_x+p1s_sl/2, 'y':p1s_y-p1s_sl/sqrt(2)}, {'x': p1_x, 'y':p1s_y} ] kicad_mod.append(PolygoneLine(polygone=p1s_poly, layer='F.SilkS', width=configuration['silk_line_width'])) p1f_sl = 2*pitch p1f_poly = [ {'x': p1_x-p1f_sl/2, 'y':body_edge['top']}, {'x': p1_x, 'y':body_edge['top']+p1f_sl/sqrt(2)}, {'x': p1_x+p1f_sl/2, 'y':body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=p1f_poly, layer='F.Fab', width=configuration['fab_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for variant in variant_params: for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, variant_params[variant], configuration) ================================================ FILE: scripts/Connector/Connector_Samtec/conn_samtec_hle.py ================================================ #!/usr/bin/env python ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = 'HLE' series_long = 'HLE .100" Tiger Beam Cost-effective Single Beam Socket Strip' manufacturer = 'Samtec' orientation = 'H' number_of_rows = 2 pitch = 2.54 datasheet_tht = 'http://suddendocs.samtec.com/prints/hle-1xx-02-xx-dv-xe-xx-mkt.pdf' datasheet_smd = 'http://suddendocs.samtec.com/prints/hle-1xx-02-xxx-dv-xx-xx-xx-mkt.pdf' footprint_tht = 'http://suddendocs.samtec.com/prints/hle-thru.pdf' footprint_smd = 'http://suddendocs.samtec.com/prints/hle-dv-footprint.pdf' # BE = Bottem Enty # TE = Top Entry # PE = Pass Through Entry drill = 0.71 pe_npth_drill = 1.4 be_npth_drill = 0.97 lc_npth_drill = 1.19 a_npth_drill = 1.78 pad_size_smd = [1.27, 2.29] pad_size_smd_be = [1.27, 1.68] pad_pitch_y_smd = 5.05 pad_pitch_y_smd_be = 5.44 pad_pitch_y_pe = 7.62 pad_to_pad_clearance = 1.2 max_annular_ring = 0.3 min_annular_ring = 0.15 variant_params = { 'smd-be-a': { 'smd': True, 'pins_per_row_range': range(4,51), 'npth_drill': be_npth_drill, 'peg_drill': a_npth_drill, 'pad_size': pad_size_smd_be, 'pad_pitch_y': pad_pitch_y_smd_be, 'datasheets': [datasheet_smd, footprint_smd], 'part_code': "HLE-1{n:02}-02-xxx-DV-BE-A", }, 'smd-be-lc': { 'smd': True, 'pins_per_row_range': range(2,51), 'npth_drill': be_npth_drill, 'peg_drill': lc_npth_drill, 'pad_size': pad_size_smd_be, 'pad_pitch_y': pad_pitch_y_smd_be, 'datasheets': [datasheet_smd, footprint_smd], 'part_code': "HLE-1{n:02}-02-xxx-DV-BE-LC", }, 'smd-be': { 'smd': True, 'pins_per_row_range': range(2,51), 'npth_drill': be_npth_drill, 'pad_size': pad_size_smd_be, 'pad_pitch_y': pad_pitch_y_smd_be, 'datasheets': [datasheet_smd, footprint_smd], 'part_code': "HLE-1{n:02}-02-xxx-DV-BE", }, 'smd-a': { 'smd': True, 'pins_per_row_range': range(4,51), 'peg_drill': a_npth_drill, 'pad_size': pad_size_smd, 'pad_pitch_y': pad_pitch_y_smd, 'datasheets': [datasheet_smd, footprint_smd], 'part_code': "HLE-1{n:02}-02-xxx-DV-A", }, 'smd-lc': { 'smd': True, 'pins_per_row_range': range(2,51), 'peg_drill': lc_npth_drill, 'pad_size': pad_size_smd, 'pad_pitch_y': pad_pitch_y_smd, 'datasheets': [datasheet_smd, footprint_smd], 'part_code': "HLE-1{n:02}-02-xxx-DV-LC", }, 'smd': { 'smd': True, 'pins_per_row_range': range(2,51), 'pad_size': pad_size_smd, 'pad_pitch_y': pad_pitch_y_smd, 'datasheets': [datasheet_smd, footprint_smd], 'part_code': "HLE-1{n:02}-02-xxx-DV", }, 'tht-te': { 'pins_per_row_range': range(4,51), 'pad_drill': drill, 'datasheets': [datasheet_tht, footprint_tht], 'part_code': "HLE-1{n:02}-02-xx-DV-TE", }, 'tht-pe': { 'pins_per_row_range': range(4,51), 'npth_drill': pe_npth_drill, 'pad_drill': drill, 'pad_pitch_y': pad_pitch_y_pe, 'datasheets': [datasheet_tht, footprint_tht], 'part_code': "HLE-1{n:02}-02-xx-DV-PE", 'alternative_codes': [ "HLE-1{n:02}-02-xx-DV-PE-BE" ], }, 'tht-pe-lc': { 'pins_per_row_range': range(4,51), 'npth_drill': pe_npth_drill, 'peg_drill': lc_npth_drill, 'pad_drill': drill, 'pad_pitch_y': pad_pitch_y_pe, 'datasheets': [datasheet_tht, footprint_tht], 'part_code': "HLE-1{n:02}-02-xx-DV-PE-LC", }, } def generate_one_footprint(pins_per_row, variant, configuration): is_smd = variant_params[variant].get('smd', False) mpn = variant_params[variant]['part_code'].format(n=pins_per_row) alt_mpn = [code.format(n=pins_per_row) for code in variant_params[variant].get('alternative_codes', [])] # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format( man=manufacturer, series='', mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, pitch=pitch, mounting_pad = "", orientation=orientation_str) footprint_name = footprint_name.replace('__','_') kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{manufacturer} {series}, {mpn}{alt_mpn}, {pins_per_row} Pins per row ({datasheet}), generated with kicad-footprint-generator".format( manufacturer = manufacturer, series = series_long, mpn = mpn, alt_mpn = ' (compatible alternatives: {})'.format(', '.join(alt_mpn)) if len(alt_mpn) > 0 else "", pins_per_row = pins_per_row, datasheet = ', '.join(variant_params[variant]['datasheets']))) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) if is_smd: kicad_mod.setAttribute('smd') ########################## Dimensions ############################## # Solder pads pitch pad_pitch_x = pitch pad_pitch_y = variant_params[variant].get('pad_pitch_y', pitch) # Size of the connector (without pins) size_x = pins_per_row * pitch size_y = 5.08 # Offset everything if is_smd: offset_x = -size_x/2 + pitch/2 offset_y = -size_y/2 + pitch/2 else: offset_x = 0 offset_y = (pad_pitch_y - pitch)/2 # Position of connector pins. This is either used for npth holes at pin position or for tht pads pin_row1_y = offset_y + 0 pin_row2_y = pin_row1_y + pitch pin1_x = offset_x + 0 if is_smd: pad1_x = pin1_x pad_row1_y = offset_y + pitch/2 - pad_pitch_y/2 pad_row2_y = pad_row1_y + pad_pitch_y pad_size = variant_params[variant].get('pad_size', None) pad_shape = Pad.SHAPE_RECT pad1_shape = pad_shape pad_layer = Pad.LAYERS_SMT pad_type = Pad.TYPE_SMT pad_drill = None else: # By definition pad1 needs to be at 0,0 for THT pad1_x = 0 pad_row1_y = 0 pad_row2_y = pad_row1_y + pad_pitch_y pad_layer = Pad.LAYERS_THT pad_drill = variant_params[variant].get('pad_drill', None) pad_type = Pad.TYPE_THT pad_size = [pitch - pad_to_pad_clearance, pad_drill + 2*max_annular_ring] if pad_size[0] - pad_drill < 2*min_annular_ring: pad_size[0] = pad_drill + 2*min_annular_ring if pad_size[0] - pad_drill > 2*max_annular_ring: pad_size[0] = pad_drill + 2*max_annular_ring if pad_size[1] - pad_drill < 2*min_annular_ring: pad_size[1] = pad_drill + 2*min_annular_ring if pad_size[1] - pad_drill > 2*max_annular_ring: pad_size[1] = pad_drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE peg1_x = offset_x + pitch/2 peg2_x = offset_x - pitch/2 + size_x - pitch peg_y = offset_y + pitch/2 body_edge={ 'left': offset_x - pitch/2, 'right': offset_x + size_x - pitch/2, 'top': offset_y - pitch/2, 'bottom': offset_y + size_y - pitch/2, } bounding_box={ 'left': body_edge['left'], 'right': body_edge['right'], 'top': min(pad_row1_y - pad_size[1]/2, body_edge['top']), 'bottom': max(pad_row2_y + pad_size[1]/2, body_edge['bottom']), } # ############################# Pads ################################## # Pegs peg_drill = variant_params[variant].get('peg_drill', None) if peg_drill != None: kicad_mod.append(Pad(at=[peg1_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) if (peg1_x != peg2_x): kicad_mod.append(Pad(at=[peg2_x, peg_y], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) # NPTH Holes for Connector Pins npth_drill = variant_params[variant].get('npth_drill', None) if npth_drill: for x in range(0, pins_per_row): for y in range(0, number_of_rows): kicad_mod.append(Pad(at=[pin1_x+x*pitch, pin_row1_y+y*pitch], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=npth_drill, drill=npth_drill, layers=Pad.LAYERS_NPTH)) # Pads optional_pad_params = {} if not is_smd: if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(start=[pad1_x, pad_row1_y], initial=1, pincount=pins_per_row, increment=2, x_spacing=pitch, size=pad_size, type=pad_type, shape=pad_shape, layers=pad_layer, drill=pad_drill, **optional_pad_params)) kicad_mod.append(PadArray(start=[pad1_x, pad_row2_y], initial=2, pincount=pins_per_row, increment=2, x_spacing=pitch, size=pad_size, type=pad_type, shape=pad_shape, layers=pad_layer, drill=pad_drill, **optional_pad_params)) # ######################## Fabrication Layer ########################### poly_f = [ {'x': body_edge['left'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']}, ] kicad_mod.append(PolygoneLine(polygone=poly_f, width=configuration['fab_line_width'], layer="F.Fab")) # Pin 1 marking p1m_sl = 1 p1m_poly = [ {'x': pad1_x - p1m_sl/2, 'y': body_edge['top']}, {'x': pad1_x, 'y': body_edge['top'] + p1m_sl/sqrt(2)}, {'x': pad1_x + p1m_sl/2, 'y': body_edge['top']} ] kicad_mod.append(PolygoneLine(polygone=p1m_poly, width=configuration['fab_line_width'], layer="F.Fab")) ############################ SilkS ################################## s_pad_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 s_offset = configuration['silk_fab_offset'] # Check if we can draw a solid box for the connector or we need to interrupt it for pads if ((pad_row1_y - pad_size[1]/2 - s_pad_offset) < body_edge['top']) and ((pad_row1_y + pad_size[1]/2 + s_pad_offset) > body_edge['top']): s_xp1_left = pad1_x - pad_size[0]/2 - s_pad_offset s_xpn_right = pad1_x + size_x - pitch + pad_size[0]/2 + s_pad_offset poly_s_l = [ {'x': s_xp1_left, 'y': pad_row1_y - pad_size[1]/2}, {'x': s_xp1_left, 'y': body_edge['top'] - s_offset}, {'x': body_edge['left'] - s_offset, 'y': body_edge['top'] - s_offset}, {'x': body_edge['left'] - s_offset, 'y': body_edge['bottom'] + s_offset}, {'x': s_xp1_left, 'y': body_edge['bottom'] + s_offset}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_l, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_r = [ {'x': s_xpn_right, 'y': body_edge['top'] - s_offset}, {'x': body_edge['right'] + s_offset, 'y': body_edge['top'] - s_offset}, {'x': body_edge['right'] + s_offset, 'y': body_edge['bottom'] + s_offset}, {'x': s_xpn_right, 'y': body_edge['bottom'] + s_offset}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_r, width=configuration['silk_line_width'], layer="F.SilkS")) for i in range(0, pins_per_row-1): s_xpi_left = pad1_x + i * pitch + pad_size[0]/2 + s_pad_offset s_xpi_right = pad1_x + (i+1) * pitch - pad_size[0]/2 - s_pad_offset poly_s_t = [ {'x': s_xpi_left, 'y': body_edge['top'] - s_offset}, {'x': s_xpi_right, 'y': body_edge['top'] - s_offset}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_t, width=configuration['silk_line_width'], layer="F.SilkS")) poly_s_b = [ {'x': s_xpi_left, 'y': body_edge['bottom'] + s_offset}, {'x': s_xpi_right, 'y': body_edge['bottom'] + s_offset}, ] kicad_mod.append(PolygoneLine(polygone=poly_s_b, width=configuration['silk_line_width'], layer="F.SilkS")) else: poly_s = [ {'x': body_edge['left'] - s_offset, 'y': body_edge['top'] - s_offset}, {'x': body_edge['right'] + s_offset, 'y': body_edge['top'] - s_offset}, {'x': body_edge['right'] + s_offset, 'y': body_edge['bottom'] + s_offset}, {'x': body_edge['left'] - s_offset, 'y': body_edge['bottom'] + s_offset}, {'x': body_edge['left'] - s_offset, 'y': body_edge['top'] - s_offset}, ] kicad_mod.append(PolygoneLine(polygone=poly_s, width=configuration['silk_line_width'], layer="F.SilkS")) # ############################ CrtYd ################################## cy_offset = configuration['courtyard_offset']['connector'] cy_grid = configuration['courtyard_grid'] cy_top = roundToBase(bounding_box['top'] - cy_offset, cy_grid) cy_bottom = roundToBase(bounding_box['bottom'] + cy_offset, cy_grid) cy_left = roundToBase(bounding_box['left'] - cy_offset, cy_grid) cy_right = roundToBase(bounding_box['right'] + cy_offset, cy_grid) poly_cy = [ {'x': cy_left, 'y': cy_top}, {'x': cy_right, 'y': cy_top}, {'x': cy_right, 'y': cy_bottom}, {'x': cy_left, 'y': cy_bottom}, {'x': cy_left, 'y': cy_top}, ] kicad_mod.append(PolygoneLine(polygone=poly_cy, layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy_top, 'bottom':cy_bottom}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name_suffix = '_SMD' if is_smd else '_THT' lib_name = configuration['lib_name_format_string_full'].format(series=series, man=manufacturer, suffix=lib_name_suffix) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: for pins_per_row in variant_params[variant]['pins_per_row_range']: generate_one_footprint(pins_per_row, variant, configuration) ================================================ FILE: scripts/Connector/Connector_Samtec/helpers.py ================================================ def roundToBase(value, base): if base == 0: return value return round(value/base) * base ================================================ FILE: scripts/Connector/Connector_Samtec/mecf_connector.py ================================================ #!/usr/bin/env python3 import sys import os import math from operator import add from helpers import * from math import sqrt import argparse import yaml # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load kicad_mod path from KicadModTree import * # NOQA # from drawing_tools import * # from footprint_scripts_potentiometers import * from footprint_text_fields import addTextFields lib_name_category = 'PCBEdge' pinrange = ['05', '08', '20', '30', '40', '50', '60', '70'] pad_size = [0.56,4.00] layers_top = ['F.Cu', 'F.Mask'] layers_bottom = ['B.Cu', 'B.Mask'] pad_type = Pad.TYPE_CONNECT K = { '05': 8.10, '08': 11.91, '20': 27.15, '30': 39.85, '40': 52.55, '50': 65.25, '60': 77.95, '70': 90.65 } L = { '05': 2.79, '08': 4.06, '20': 10.41, '30': 14.22, '40': 20.57, '50': 26.92, '60': 20.57, '70': 34.54 } M = { '60': 40.89, '70': 73.91 } POL = { '05': [ 3], '08': [ 5], '20': [15], '30': [21], '40': [31], '50': [41], '60': [31, 63], '70': [53, 115] } def generate_one_footprint(pol, n, configuration): off = configuration['silk_fab_offset'] CrtYd_offset = configuration['courtyard_offset']['default'] fp_name = 'Samtec_MECF-' + n + '-0_-' if pol == False: fp_name = fp_name + 'NP-' fp_name += 'L-DV' fp_name += '_{:d}x{:02d}_P{:.2f}mm'.format(2,int(n),1.27) if pol: fp_name += '_Polarized' fp_name += '_Edge' kicad_mod = Footprint(fp_name) description = "Highspeed card edge connector for PCB's with " + n + " contacts " if pol == True: description = description + '(polarized)' else: description = description + '(not polarized)' kicad_mod.setAttribute('virtual') #set the FP description kicad_mod.setDescription(description) tags = "conn samtec card-edge high-speed" #set the FP tags kicad_mod.setTags(tags) # set general values top = -(5.0) bot = (5.0) left = -(K[n]/2.0) right = (K[n]/2.0) body_edge={ 'left': left, 'right': right, 'top': top, 'bottom': bot } top_left = [left, top] bot_right = [ right, bot] # create Fab Back(exact outline) kicad_mod.append(Line(start=[left + 1.27, bot], end=[right, bot], layer='F.Fab', width=configuration['fab_line_width'])) #bot line kicad_mod.append(Line(start=[left, top], end=[ right, top], layer='F.Fab', width=configuration['fab_line_width'])) #top line kicad_mod.append(Line(start=[left, bot - 1.27], end=[left, top], layer='F.Fab', width=configuration['fab_line_width'])) #left line kicad_mod.append(Line(start=[right, bot], end=[ right, top], layer='F.Fab', width=configuration['fab_line_width'])) #right line kicad_mod.append(Line(start=[left, bot - 1.27], end=[left + 1.27, bot], layer='F.Fab', width=configuration['fab_line_width'])) #corner # create Fab Front(exact outline) kicad_mod.append(Line(start=[left, bot], end=[right, bot], layer='B.Fab', width=configuration['fab_line_width'])) #bot line kicad_mod.append(Line(start=[left, top], end=[ right, top], layer='B.Fab', width=configuration['fab_line_width'])) #top line kicad_mod.append(Line(start=[left, bot ], end=[left, top], layer='B.Fab', width=configuration['fab_line_width'])) #left line kicad_mod.append(Line(start=[right, bot], end=[ right, top], layer='B.Fab', width=configuration['fab_line_width'])) #right line top = top - off #bot = bot + 0.11 left = left - off right = right + off # create silscreen Back(exact + 0.11) kicad_mod.append(Line(start=[round(left, 2) + 1.27, round(bot, 2)], end=[round(right, 2), round(bot, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #bot line kicad_mod.append(Line(start=[round(left, 2), round(top, 2)], end=[round(right, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #top line kicad_mod.append(Line(start=[round(left, 2), round(bot, 2) - 1.27], end=[round(left, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #left line kicad_mod.append(Line(start=[round(right, 2), round( bot, 2)], end=[round(right, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #right line kicad_mod.append(Line(start=[round(left, 2) + 1.27, round(bot, 2) ], end=[round(left, 2), round(bot, 2) - 1.27], layer='F.SilkS', width=configuration['silk_line_width'])) #corner # create silscreen Front(exact + 0.11) kicad_mod.append(Line(start=[round(left, 2), round(bot, 2)], end=[round(right, 2), round(bot, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #bot line kicad_mod.append(Line(start=[round(left, 2), round(top, 2)], end=[round(right, 2), round(top, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #top line kicad_mod.append(Line(start=[round(left, 2), round(bot, 2)], end=[round(left, 2), round(top, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #left line kicad_mod.append(Line(start=[round(right, 2), round( bot, 2)], end=[round(right, 2), round(top, 2)], layer='B.SilkS', width=configuration['silk_line_width'])) #right line top = roundToBase(body_edge['top'] - CrtYd_offset, configuration['courtyard_grid']) bot = roundToBase(body_edge['bottom'], configuration['courtyard_grid']) left = roundToBase(body_edge['left'] - CrtYd_offset, configuration['courtyard_grid']) right = roundToBase(body_edge['right'] + CrtYd_offset, configuration['courtyard_grid']) cy1 = top cy2 = bot # create courtyard (exact + 0.25) kicad_mod.append(RectLine(start=[left, top], end=[right , bot], layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(RectLine(start=[left, top], end=[right , bot], layer='B.CrtYd', width=configuration['courtyard_line_width'])) top = body_edge['top'] bot = body_edge['bottom'] slot_height = 7.0 ## create cutout kicad_mod.append(Line(start=[-K[n]/2.0, bot, 2], end=[-K[n]/2.0, top, 2], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #left line kicad_mod.append(Line(start=[K[n]/2.0, bot, 2], end=[K[n]/2.0, top], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #right line ## grid ends nextGrid = math.ceil((K[n]/2.0)/0.25 + 1.0) * 0.25 #nextGrid = roundToBase(K[n]/2, 0.25) kicad_mod.append(Line(start=[-nextGrid, top, 2], end=[-K[n]/2.0, top, 2], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #left line kicad_mod.append(Line(start=[+nextGrid, top, 2], end=[K[n]/2.0, top], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #right line if pol == True: # Cutouts kicad_mod.append(Line(start=[-K[n]/2.0, bot], end=[-K[n]/2.0+L[n]-1.24/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line kicad_mod.append(Line(start=[-K[n]/2.0+L[n]-1.24/2.0, bot], end=[-K[n]/2.0+L[n]-1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #up kicad_mod.append(Line(start=[-K[n]/2.0+L[n]+1.24/2.0, bot], end=[-K[n]/2.0+L[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #down kicad_mod.append(Line(start=[-K[n]/2.0+L[n]-1.24/2.0, bot - slot_height], end=[-K[n]/2.0+L[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #cut if n in ['60','70']: kicad_mod.append(Line(start=[-K[n]/2.0+L[n]+1.24/2.0, bot], end=[-K[n]/2.0+M[n]-1.24/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line kicad_mod.append(Line(start=[-K[n]/2.0+M[n]-1.24/2.0, bot], end=[-K[n]/2.0+M[n]-1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #up kicad_mod.append(Line(start=[-K[n]/2.0+M[n]+1.24/2.0, bot], end=[-K[n]/2.0+M[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #down kicad_mod.append(Line(start=[-K[n]/2.0+M[n]-1.24/2.0, bot - slot_height], end=[-K[n]/2.0+M[n]+1.24/2.0, bot - slot_height], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #cut kicad_mod.append(Line(start=[-K[n]/2.0+M[n]+1.24/2.0, bot], end=[K[n]/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line else: kicad_mod.append(Line(start=[-K[n]/2.0+L[n]+1.24/2.0, bot], end=[K[n]/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line else: kicad_mod.append(Line(start=[-K[n]/2.0, bot], end=[K[n]/2.0, bot], layer='Edge.Cuts', width=configuration['edge_cuts_line_width'])) #bot line # create pads for i in range(0,int(n)): start = - K[n]/2.0 + 1.52 if pol == True: if (i*2+1) not in POL[n]: kicad_mod.append(Pad(number=i*2 + 1, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_top)) kicad_mod.append(Pad(number=i*2 + 2, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_bottom)) else: kicad_mod.append(Pad(number=i*2 + 1, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_top)) kicad_mod.append(Pad(number=i*2 + 2, type=pad_type, shape=Pad.SHAPE_RECT, at=[start + i*1.27, bot - 2.0 - 0.5], size=pad_size, layers=layers_bottom)) # output kicad model #print(kicad_mod # print render tree #print(kicad_mod.getRenderTree()) #print(kicad_mod.getCompleteRenderTree()) # kicad_mod.append(Text(type='reference', text='REF**', at=[0,-6.35], layer='F.SilkS')) # kicad_mod.append(Text(type='user', text='%R', at=[0,-2.54], layer='F.Fab')) # kicad_mod.append(Text(type='value', text=fp_name, at=[0,-3.81], layer='F.Fab')) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=fp_name, text_y_inside_position=-2.54) lib_name = configuration['lib_name_specific_function_format_string'].format(category=lib_name_category) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for pol in [True, False]: for pincount in pinrange: generate_one_footprint(pol, pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Samtec/mecf_socket.py ================================================ #!/usr/bin/env python3 import sys import os import math from operator import add from helpers import * from math import sqrt import argparse import yaml # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load kicad_mod path from KicadModTree import * # NOQA # from drawing_tools import * # from footprint_scripts_potentiometers import * from footprint_text_fields import addTextFields lib_name_category = 'PCBEdge' A = { '05': 8.64, '08': 12.45, '20': 27.69, '30': 40.39, '40': 53.09, '50': 65.79, '60': 78.49, '70': 91.19 } B = { '05': 5.08, '08': 8.89, '20': 24.13, '30': 36.83, '40': 49.53, '50': 62.23, '60': 74.93, '70': 87.63 } C = { '05': 2.54, '08': 3.81, '20': 10.16, '30': 13.97, '40': 20.32, '50': 26.67, '60': 20.32, '70': 34.29 } D = { '08': 1.27, '20': 7.62, '30': 11.43, '40': 17.78, '50': 24.13, '60': 17.78, '70': 31.75 } E = { '05': 12.45, '08': 16.26, '20': 31.50, '30': 44.20, '40': 56.90, '50': 69.60, '60': 82.30, '70': 95.00 } F = { '01': 3.81, '02': 4.60 } G = { '60': 40.64, '70': 73.66 } H = { '60': 38.10, '70': 71.12 } POL = { '05': [ 3], '08': [ 5], '20': [15], '30': [21], '40': [31], '50': [41], '60': [31, 63], '70': [53, 115] } pad_size = [0.66,1.35] def generate_one_footprint(weld, pol, pcb_thickness, n, configuration): off = configuration['silk_fab_offset'] CrtYd_offset = configuration['courtyard_offset']['connector'] fp_name = 'Samtec_MECF-' + n + '-' + pcb_thickness + '-' if pol == False: fp_name = fp_name + 'NP-' fp_name = fp_name + 'L-DV' if weld == True: fp_name = fp_name + '-WT' fp_name += '_{:d}x{:02d}_P{:.2f}mm'.format(2,int(n),1.27) if pol: fp_name += '_Polarized' fp_name = fp_name + '_Socket' fp_name = fp_name + '_Horizontal' kicad_mod = Footprint(fp_name) description = "Highspeed card edge connector for " if pcb_thickness == '01': description = description + '1.6mm' else: description = description + '2.4mm' description = description + " PCB's with " + n + " contacts " if pol == True: description = description + '(polarized)' else: description = description + '(not polarized)' #set the FP description kicad_mod.setDescription(description) kicad_mod.setAttribute('smd') tags = "conn samtec card-edge high-speed" #set the FP tags kicad_mod.setTags(tags) top = -(F[pcb_thickness]/2.0 + 0.9) bot = (F[pcb_thickness]/2.0 + 0.9) left = 0 right = 0 if weld == True: left = -(E[n]/2.0 + 0.91) right = (E[n]/2.0 + 0.91) else: left = -(A[n]/2.0 + 0.91) right = (A[n]/2.0 + 0.91) body_edge={ 'left': left, 'right': right, 'top': top, 'bottom': bot } top_left = [left, top] bot_right = [ right, bot] # create Fab (exact outline) kicad_mod.append(Line(start=[left + 1.27, bot], end=[right, bot], layer='F.Fab', width=configuration['fab_line_width'])) #bot line kicad_mod.append(Line(start=[left, top], end=[ right, top], layer='F.Fab', width=configuration['fab_line_width'])) #top line kicad_mod.append(Line(start=[left, bot - 1.27], end=[left, top], layer='F.Fab', width=configuration['fab_line_width'])) #left line kicad_mod.append(Line(start=[right, bot], end=[ right, top], layer='F.Fab', width=configuration['fab_line_width'])) #right line kicad_mod.append(Line(start=[left, bot - 1.27], end=[left + 1.27, bot], layer='F.Fab', width=configuration['fab_line_width'])) #corner top = top - off bot = bot + off left = left - off right = right + off # create silscreen (exact + 0.11) kicad_mod.append(Line(start=[round(left, 2) + 1.27, round(bot, 2)], end=[round(right, 2), round(bot, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #bot line kicad_mod.append(Line(start=[round(left, 2), round(top, 2)], end=[round(right, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #top line kicad_mod.append(Line(start=[round(left, 2), round(bot, 2) - 1.27], end=[round(left, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #left line kicad_mod.append(Line(start=[round(right, 2), round( bot, 2)], end=[round(right, 2), round(top, 2)], layer='F.SilkS', width=configuration['silk_line_width'])) #right line kicad_mod.append(Line(start=[round(left, 2) + 1.27, round(bot, 2) ], end=[round(left, 2), round(bot, 2) - 1.27], layer='F.SilkS', width=configuration['silk_line_width'])) #corner top = roundToBase(body_edge['top'] - CrtYd_offset, configuration['courtyard_grid']) bot = roundToBase(body_edge['bottom'] + CrtYd_offset, configuration['courtyard_grid']) left = roundToBase(body_edge['left'] - CrtYd_offset, configuration['courtyard_grid']) right = roundToBase(body_edge['right'] + CrtYd_offset, configuration['courtyard_grid']) cy1 = top cy2 = bot # create courtyard (exact + 0.25) kicad_mod.append(RectLine(start=[round(left,2), round(top,2)], end=[round(right,2), round(bot,2)], layer='F.CrtYd', width=configuration['courtyard_line_width'])) # create pads for i in range(0,int(n)): start = - B[n]/2.0 if pol == True: if (i*2+1) not in POL[n]: kicad_mod.append(Pad(number=i*2 + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[start + i*1.27, F[pcb_thickness]/2.0], size=pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number=i*2 + 2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[start + i*1.27, - F[pcb_thickness]/2.0], size=pad_size, layers=Pad.LAYERS_SMT)) else: kicad_mod.append(Pad(number=i*2 + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[start + i*1.27, F[pcb_thickness]/2.0], size=pad_size, layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number=i*2 + 2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[start + i*1.27, - F[pcb_thickness]/2.0], size=pad_size, layers=Pad.LAYERS_SMT)) drill = 1.45 kicad_mod.append(Pad(number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[-A[n]/2.0, 0], size=drill, drill=drill, layers=Pad.LAYERS_NPTH)) kicad_mod.append(Pad(number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[A[n]/2.0, 1.0], size=drill, drill=drill, layers=Pad.LAYERS_NPTH)) if weld == True: size = [1.5,1.5] drill = 1 kicad_mod.append(Pad(number="", type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[-E[n]/2.0, 0], size=size, drill=drill, layers=Pad.LAYERS_THT)) kicad_mod.append(Pad(number="", type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[ E[n]/2.0, 0.0], size=size, drill=drill, layers=Pad.LAYERS_THT)) # output kicad model #print(kicad_mod # kicad_mod.append(Text(type='reference', text='REF**', at=[0,3.81], layer='F.SilkS')) # kicad_mod.append(Text(type='user', text='%R', at=[0,0], layer='F.Fab')) # kicad_mod.append(Text(type='value', text=fp_name, at=[0,-3.81], layer='F.Fab')) addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') #lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) lib_name = configuration['lib_name_specific_function_format_string'].format(category=lib_name_category) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == '__main__': parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) for weld in [True, False]: for pol in [True, False]: for pcb_thickness in ['01', '02']: for n in ['05', '08', '20', '30', '40', '50', '60', '70']: generate_one_footprint(weld, pol, pcb_thickness, n, configuration) ================================================ FILE: scripts/Connector/Connector_Stocko/conn_Stocko_MKS_16xx.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from KicadModTree import * output_dir = "Connector_Stocko.pretty" if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) #connector constraints pad_span = 2.5 pad_size_x = 1.5 pad_size_y = 2 drill = 1 fab_outline_x = 3.6 fab_outline_y = 3.75 fab_cut_depth = 2 fab_cut_width = 2 fab_arc_r = 0.5 fab_first_pin = 0.5 silks_outline_x = fab_outline_x + 0.11 silks_outline_y = fab_outline_y + 0.11 silks_cut_depth = 2 silks_cut_width = 2 + 0.22 silks_arc_r = fab_arc_r + 0.11 courtyard_outline = 0.5 for itr in range (1, 20 + 1): # for special case, details: https://www.stocko-contact.com/en/products-connector-system-pitch-2.5-mm-rfk-2-mks-1650.php if itr == 1: pin_count = 2 elif itr == 2: pin_count = 2 fab_outline_x = 2.7 silks_outline_x = fab_outline_x + 0.11 else: pin_count = itr fab_outline_x = 3.6 silks_outline_x = fab_outline_x + 0.11 #init kicad footprint footprint_name = "Stocko_MKS_16{}-6-0-{}{:02d}_1x{}_P2.50mm_Vertical".format(50 + itr, pin_count, pin_count, pin_count) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("Stocko MKS 16xx series connector, (https://www.stocko-contact.com/downloads/steckverbindersystem-raster-2,5-mm.pdf#page=15), generated with kicad-footprint-generator") kicad_mod.setTags("Stocko RFK MKS 16xx") #CREATE PIN #first rectangle pin kicad_mod.append(Pad(number = 1, type = Pad.TYPE_THT, shape = Pad.SHAPE_ROUNDRECT, at=[0, 0], size=[pad_size_x, pad_size_y], drill=drill, layers=Pad.LAYERS_THT, radius_ratio=0.25)) #circle pin for pin_cnt in range (2, pin_count + 1): kicad_mod.append(Pad(number = pin_cnt, type = Pad.TYPE_THT, shape = Pad.SHAPE_OVAL, at=[(pin_cnt - 1) * pad_span, 0], size=[pad_size_x, pad_size_y], drill=drill, layers = Pad.LAYERS_THT)) #CREATE SILKSCREEN #name kicad_mod.append(Text(type = 'reference', text='REF**', at=[(pin_count - 1) * (pad_span / 2), -4.5], layer='F.SilkS')) #top kicad_mod.append(Line(start = [-silks_outline_x + silks_arc_r, -silks_outline_y], end = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_arc_r, -silks_outline_y], layer = 'F.SilkS')) #left kicad_mod.append(Line(start = [-silks_outline_x, -silks_outline_y + silks_arc_r], end = [-silks_outline_x, silks_outline_y - silks_arc_r], layer = 'F.SilkS')) #right kicad_mod.append(Line(start = [(pin_cnt - 1) * pad_span + silks_outline_x, -silks_outline_y + silks_arc_r], end = [(pin_cnt - 1) * pad_span + silks_outline_x, silks_outline_y - silks_arc_r], layer = 'F.SilkS')) #bottom left kicad_mod.append(Line(start = [-silks_outline_x + silks_arc_r, silks_outline_y], end = [-silks_outline_x + silks_cut_width, silks_outline_y], layer = 'F.SilkS')) kicad_mod.append(Line(start = [-silks_outline_x + silks_cut_width, silks_outline_y], end = [-silks_outline_x + silks_cut_width, silks_outline_y - silks_cut_depth], layer = 'F.SilkS')) #bottom right kicad_mod.append(Line(start = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_arc_r, silks_outline_y], end = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_cut_width, silks_outline_y], layer = 'F.SilkS')) kicad_mod.append(Line(start = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_cut_width, silks_outline_y], end = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_cut_width, silks_outline_y - silks_cut_depth], layer = 'F.SilkS')) #bottom center kicad_mod.append(Line(start = [-silks_outline_x + silks_cut_width, silks_outline_y - silks_cut_depth], end = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_cut_width, silks_outline_y - silks_cut_depth], layer = 'F.SilkS')) #arc left top kicad_mod.append(Arc(center = [-silks_outline_x + silks_arc_r, -silks_outline_y + silks_arc_r], start = [-silks_outline_x, -silks_outline_y + silks_arc_r], angle = 90, layer = 'F.SilkS')) #arc right top kicad_mod.append(Arc(center = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_arc_r, -silks_outline_y + silks_arc_r], start = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_arc_r, -silks_outline_y], angle = 90, layer = 'F.SilkS')) #arc left bottom kicad_mod.append(Arc(center = [-silks_outline_x + silks_arc_r, silks_outline_y - silks_arc_r], start = [-silks_outline_x + silks_arc_r, silks_outline_y], angle = 90, layer = 'F.SilkS')) #arc right bottom kicad_mod.append(Arc(center = [(pin_cnt - 1) * pad_span + silks_outline_x - silks_arc_r, silks_outline_y - silks_arc_r], start = [(pin_cnt - 1) * pad_span + silks_outline_x, silks_outline_y - silks_arc_r], angle = 90, layer = 'F.SilkS')) #first pin indicator kicad_mod.append(Line(start = [0.3, 2.9], end = [0, 2.4], layer = 'F.SilkS')) kicad_mod.append(Line(start = [0, 2.4], end = [-0.3, 2.9], layer = 'F.SilkS')) kicad_mod.append(Line(start = [-0.3, 2.9], end = [0.3, 2.9], layer = 'F.SilkS')) #CREATE FABRICATION #name kicad_mod.append(Text(type = 'user', text = '%R', at = [(pin_count - 1) * (pad_span / 2), -2], layer = 'F.Fab')) kicad_mod.append(Text(type = 'value', text = footprint_name, at = [(pin_count - 1) * (pad_span / 2), silks_outline_y + 2], layer = 'F.Fab')) #top kicad_mod.append(Line(start = [-fab_outline_x + fab_arc_r, -fab_outline_y], end = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_arc_r, -fab_outline_y], layer = 'F.Fab')) #left kicad_mod.append(Line(start = [-fab_outline_x, -fab_outline_y + fab_arc_r], end = [-fab_outline_x, fab_outline_y - fab_arc_r], layer = 'F.Fab')) #right kicad_mod.append(Line(start = [(pin_cnt - 1) * pad_span + fab_outline_x, -fab_outline_y + fab_arc_r], end = [(pin_cnt - 1) * pad_span + fab_outline_x, fab_outline_y - fab_arc_r], layer = 'F.Fab')) #bottom left kicad_mod.append(Line(start = [-fab_outline_x + fab_arc_r, fab_outline_y], end = [-fab_outline_x + fab_cut_width, fab_outline_y], layer = 'F.Fab')) kicad_mod.append(Line(start = [-fab_outline_x + fab_cut_width, fab_outline_y], end = [-fab_outline_x + fab_cut_width, fab_outline_y - fab_cut_depth], layer = 'F.Fab')) #bottom right kicad_mod.append(Line(start = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_arc_r, fab_outline_y], end = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_cut_width, fab_outline_y], layer = 'F.Fab')) kicad_mod.append(Line(start = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_cut_width, fab_outline_y], end = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_cut_width, fab_outline_y - fab_cut_depth], layer = 'F.Fab')) #bottom center and first pin indicator kicad_mod.append(Line(start = [-fab_outline_x + fab_cut_width, fab_outline_y - fab_cut_depth], end = [-fab_first_pin, fab_outline_y - fab_cut_depth], layer = 'F.Fab')) kicad_mod.append(Line(start = [fab_first_pin, fab_outline_y - fab_cut_depth], end = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_cut_width, fab_outline_y - fab_cut_depth], layer = 'F.Fab')) kicad_mod.append(Line(start = [-fab_first_pin, fab_outline_y - fab_cut_depth], end = [0, fab_outline_y - fab_cut_depth - fab_first_pin], layer = 'F.Fab')) kicad_mod.append(Line(start = [0, fab_outline_y - fab_cut_depth - fab_first_pin], end = [fab_first_pin, fab_outline_y - fab_cut_depth], layer = 'F.Fab')) #arc left top kicad_mod.append(Arc(center = [-fab_outline_x + fab_arc_r, -fab_outline_y + fab_arc_r], start = [-fab_outline_x, -fab_outline_y + fab_arc_r], angle = 90, layer = 'F.Fab')) #arc right top kicad_mod.append(Arc(center = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_arc_r, -fab_outline_y + fab_arc_r], start = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_arc_r, -fab_outline_y], angle = 90, layer = 'F.Fab')) #arc left bottom kicad_mod.append(Arc(center = [-fab_outline_x + fab_arc_r, fab_outline_y - fab_arc_r], start = [-fab_outline_x + fab_arc_r, fab_outline_y], angle = 90, layer = 'F.Fab')) #arc right bottom kicad_mod.append(Arc(center = [(pin_cnt - 1) * pad_span + fab_outline_x - fab_arc_r, fab_outline_y - fab_arc_r], start = [(pin_cnt - 1) * pad_span + fab_outline_x, fab_outline_y - fab_arc_r], angle = 90, layer = 'F.Fab')) #CREATE COURTYARD kicad_mod.append(RectLine(start = [-fab_outline_x - courtyard_outline, -fab_outline_y - courtyard_outline], end = [(pin_cnt - 1) * pad_span + fab_outline_x + courtyard_outline, fab_outline_y + courtyard_outline], layer = 'F.CrtYd')) #add 3D model kicad_mod.append(Model(filename="${{KISYS3DMOD}}/Connector_Stocko.3dshapes/{}.wrl".format(footprint_name), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) #output kicad model file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(output_dir + '/' + footprint_name + '.kicad_mod') ================================================ FILE: scripts/Connector/Connector_TE-Connectivity/conn_ffc_te_84952-84953.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, """ This family of parts is spread over 2 datasheets, depending on the contact side: Bottom contact: http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=84952&DocType=Customer+Drawing&DocLang=English&DocFormat=pdf&PartCntxt=1-84952-5 Top contact: http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=84953&DocType=Customer+Drawing&DocLang=English&DocFormat=pdf&PartCntxt=1-84953-5 """ import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields manufacturer = "TE-Connectivity" conn_category = "FFC-FPC" lib_by_conn_category = True partnumbers = ["84952","84953"] pincounts = range(4, 31) def generate_one_footprint(partnumber, pincount, configuration): # only double digit pincount parts have leading chars on the PN if pincount >= 10: pn_prefix = str(pincount)[0] + "-" else: pn_prefix = "" footprint_name = 'TE_{pnp}{pn:s}-{pns}_1x{pc:02g}-1MP_P1.0mm_Horizontal'\ .format(pnp=pn_prefix, pn=partnumber, pns=str(pincount)[-1], pc=pincount) print('Building {:s}'.format(footprint_name)) # calculate working values pitch = 1 pad_y = -1.8 pad_width = 0.61 pad_height = 2 pad_x_span = pitch * (pincount - 1) pad1_x = pad_x_span / 2.0 tab_width = 4.33 - 1.65 tab_height = 3.6 tab_x = pad_x_span / 2.0 + 1.65 + tab_width / 2.0 tab_y = pad_y + pad_height / 2.0 + tab_height / 2.0 body_y1 = pad_y + pad_height / 2.0 half_body_width = pad_x_span / 2.0 + 3.435 actuator_y1 = body_y1 + 5.4 actuator_y2 = body_y1 + 7.3 half_actuator_width = pad_x_span / 2.0 + 4.46 ear_height = 0.89 body_edge = { 'left': -half_body_width, 'right': half_body_width, 'top': body_y1, 'bottom': actuator_y1 } silk_clearance = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 marker_y = 1.8 nudge = configuration['silk_fab_offset'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(half_actuator_width + courtyard_clearance, courtyard_precision) courtyard_y1 = roundToBase(pad_y - pad_height / 2.0 - courtyard_clearance, courtyard_precision) courtyard_y2 = roundToBase(actuator_y2 + courtyard_clearance, courtyard_precision) label_y_offset = 0.7 # select correct datasheet URL depending on part number if partnumber == "84952": datasheet = "http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=84952&DocType=Customer+Drawing&DocLang=English&DocFormat=pdf&PartCntxt=84952-4" side = "bottom" elif partnumber == "84953": datasheet = "http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=84953&DocType=Customer+Drawing&DocLang=English&DocFormat=pdf&PartCntxt=84953-4" side = "top" # initialise footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription('TE FPC connector, {pc:02g} {side}-side contacts, 1.0mm pitch, 1.0mm height, SMT, {ds}'.format(pc=pincount, side=side, ds=datasheet)) kicad_mod.setTags('te fpc {:s}'.format(partnumber)) kicad_mod.setAttribute('smd') # create pads kicad_mod.append(PadArray(pincount=pincount, x_spacing=pitch, center=[0,pad_y], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height], layers=Pad.LAYERS_SMT)) # create tab (smt mounting) pads kicad_mod.append(Pad(number=configuration['mounting_pad_number'], at=[-tab_x, tab_y], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[tab_width, tab_height], layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number=configuration['mounting_pad_number'], at=[tab_x, tab_y], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[tab_width, tab_height], layers=Pad.LAYERS_SMT)) # create fab outline and pin 1 marker kicad_mod.append(PolygoneLine( polygone=[ [-half_body_width, body_y1], [half_body_width, body_y1], [half_body_width, actuator_y1-ear_height], [half_actuator_width, actuator_y1-ear_height], [half_actuator_width, actuator_y1], [-half_actuator_width, actuator_y1], [-half_actuator_width, actuator_y1-ear_height], [-half_body_width, actuator_y1-ear_height], [-half_body_width, body_y1]], layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ [-pad1_x-0.5, body_y1], [-pad1_x, body_y1+1], [-pad1_x+0.5, body_y1]], layer='F.Fab', width=configuration['fab_line_width'])) # create open actuator outline kicad_mod.append(PolygoneLine( polygone=[ [half_body_width, actuator_y1], [half_body_width, actuator_y2-ear_height], [half_actuator_width, actuator_y2-ear_height], [half_actuator_width, actuator_y2], [-half_actuator_width, actuator_y2], [-half_actuator_width, actuator_y2-ear_height], [-half_body_width, actuator_y2-ear_height], [-half_body_width, actuator_y1]], layer='F.Fab', width=configuration['fab_line_width'])) # create silkscreen outline and pin 1 marker kicad_mod.append(PolygoneLine( polygone=[ [half_body_width+nudge, tab_y+tab_height/2.0+silk_clearance], [half_body_width+nudge, actuator_y1-ear_height-nudge], [half_actuator_width+nudge, actuator_y1-ear_height-nudge], [half_actuator_width+nudge, actuator_y1+nudge], [-half_actuator_width-nudge, actuator_y1+nudge], [-half_actuator_width-nudge, actuator_y1-ear_height-nudge], [-half_body_width-nudge, actuator_y1-ear_height-nudge], [-half_body_width-nudge, tab_y+tab_height/2.0+silk_clearance]], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ [-tab_x+tab_width/2.0+silk_clearance, body_y1-nudge], [-pad1_x-pad_width/2.0-silk_clearance, body_y1-nudge], [-pad1_x-pad_width/2.0-silk_clearance, body_y1-nudge-marker_y]], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(Line( start=[pad1_x+pad_width/2.0+silk_clearance, body_y1-nudge], end=[tab_x-tab_width/2.0-silk_clearance, body_y1-nudge], layer='F.SilkS', width=configuration['silk_line_width'])) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, courtyard_y1], end=[courtyard_x, courtyard_y2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) # kicad_mod.append(Text(type='reference', text='REF**', size=[1,1], at=[0, courtyard_y1 - label_y_offset], layer='F.SilkS')) # kicad_mod.append(Text(type='user', text='%R', size=[1,1], at=[0, tab_y], layer='F.Fab')) # kicad_mod.append(Text(type='value', text=footprint_name, at=[0, courtyard_y2 + label_y_offset], layer='F.Fab')) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':courtyard_y1, 'bottom':courtyard_y2}, fp_name=footprint_name, text_y_inside_position=[0, tab_y]) ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == '__main__': parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) # with pincount(s) and partnumber(s) to be generated, build them all in a nested loop for partnumber in partnumbers: for pincount in pincounts: generate_one_footprint(partnumber, pincount, configuration) ================================================ FILE: scripts/Connector/Connector_TE-Connectivity/conn_fpc_te_1734839.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, """ Drawing: https://www.te.com/commerce/DocumentDelivery/DDEController?Action=showdoc&DocId=Customer+Drawing%7F1734839%7FC%7Fpdf%7FEnglish%7FENG_CD_1734839_C_C_1734839.pdf%7F4-1734839-0 """ import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields manufacturer = "TE-Connectivity" conn_category = "FFC-FPC" lib_by_conn_category = True partnumbers = ["1734839"] pincounts = range(5, 51) def generate_one_footprint(partnumber, pincount, configuration): # leading chars on the PN if pincount >= 10: pn_prefix = str(pincount)[0] + "-" else: pn_prefix = "0-" footprint_name = 'TE_{pnp}{pn:s}-{pns}_1x{pc:02g}-1MP_P0.5mm_Horizontal'\ .format(pnp=pn_prefix, pn=partnumber, pns=str(pincount)[-1], pc=pincount) print('Building {:s}'.format(footprint_name)) # calculate working values pitch = 0.5 pad_y = -1.35 pad_width = 0.3 pad_height = 1.1 pad_x_span = pitch * (pincount - 1) pad1_x = pad_x_span / 2.0 tab_width = 2.3 tab_height = 3.1 tab_x = pad_x_span / 2.0 + 2.82 - tab_width / 2.0 tab_y = pad_y - pad_height / 2.0 + 0.7 + tab_height / 2.0 body_y1 = pad_y + 0.7 half_body_width = pad_x_span / 2.0 + 2.31 actuator_y1 = body_y1 + 4.4 half_actuator_width = pad_x_span / 2.0 + 2.965 ear_height = 4.4 - 2.8 pcb_edge_gap = 0.6 body_edge = { 'left': -half_body_width, 'right': half_body_width, 'top': body_y1, 'bottom': actuator_y1 } silk_clearance = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 nudge = configuration['silk_fab_offset'] courtyard_precision = configuration['courtyard_grid'] courtyard_clearance = configuration['courtyard_offset']['connector'] courtyard_x = roundToBase(half_actuator_width + courtyard_clearance, courtyard_precision) courtyard_y1 = roundToBase(pad_y - pad_height / 2.0 - courtyard_clearance, courtyard_precision) courtyard_y2 = roundToBase(actuator_y1 + courtyard_clearance, courtyard_precision) label_y_offset = 0.7 datasheet = "https://www.te.com/commerce/DocumentDelivery/DDEController?Action=showdoc&DocId=Customer+Drawing%7F1734839%7FC%7Fpdf%7FEnglish%7FENG_CD_1734839_C_C_1734839.pdf%7F4-1734839-0" side = "top" # initialise footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription('TE FPC connector, {pc:02g} {side}-side contacts, 0.5mm pitch, SMT, {ds}'.format(pc=pincount, side=side, ds=datasheet)) kicad_mod.setTags('te fpc {:s}'.format(partnumber)) kicad_mod.setAttribute('smd') # create pads kicad_mod.append(PadArray(pincount=pincount, x_spacing=pitch, center=[0,pad_y], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[pad_width, pad_height], layers=Pad.LAYERS_SMT)) # create tab (smt mounting) pads kicad_mod.append(Pad(number=configuration['mounting_pad_number'], at=[-tab_x, tab_y], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[tab_width, tab_height], layers=Pad.LAYERS_SMT)) kicad_mod.append(Pad(number=configuration['mounting_pad_number'], at=[tab_x, tab_y], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[tab_width, tab_height], layers=Pad.LAYERS_SMT)) # create fab outline kicad_mod.append(PolygoneLine( polygone=[ [-half_body_width, body_y1], [half_body_width, body_y1], [half_body_width, actuator_y1-ear_height], [half_actuator_width, actuator_y1-ear_height], [half_actuator_width, actuator_y1], [-half_actuator_width, actuator_y1], [-half_actuator_width, actuator_y1-ear_height], [-half_body_width, actuator_y1-ear_height], [-half_body_width, body_y1]], layer='F.Fab', width=configuration['fab_line_width'])) # create fab pin 1 marker kicad_mod.append(PolygoneLine( polygone=[ [-pad1_x-0.4, body_y1], [-pad1_x, body_y1+0.8], [-pad1_x+0.4, body_y1]], layer='F.Fab', width=configuration['fab_line_width'])) # create silkscreen outline kicad_mod.append(PolygoneLine( polygone=[ [-half_actuator_width, actuator_y1-nudge-ear_height], [-half_actuator_width-nudge, actuator_y1-nudge-ear_height], [-half_actuator_width-nudge, actuator_y1-ear_height+pcb_edge_gap-nudge]], layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine( polygone=[ [half_actuator_width, actuator_y1-nudge-ear_height], [half_actuator_width+nudge, actuator_y1-nudge-ear_height], [half_actuator_width+nudge, actuator_y1-ear_height+pcb_edge_gap-nudge]], layer='F.SilkS', width=configuration['silk_line_width'])) # create silkscreen pin 1 marker kicad_mod.append(PolygoneLine( polygone=[ [-pad1_x-0.2, body_y1+0.1], [-pad1_x, body_y1+0.5], [-pad1_x+0.2, body_y1+0.1], [-pad1_x-0.2, body_y1+0.1]], layer='F.SilkS', width=configuration['silk_line_width'])) # create PCB edge kicad_mod.append(PolygoneLine( polygone=[ [half_actuator_width-nudge, actuator_y1-ear_height+pcb_edge_gap], [-half_actuator_width+nudge, actuator_y1-ear_height+pcb_edge_gap]], layer='Dwgs.User', width=configuration['fab_line_width'])) # create courtyard kicad_mod.append(RectLine(start=[-courtyard_x, courtyard_y1], end=[courtyard_x, courtyard_y2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) # kicad_mod.append(Text(type='reference', text='REF**', size=[1,1], at=[0, courtyard_y1 - label_y_offset], layer='F.SilkS')) # kicad_mod.append(Text(type='user', text='%R', size=[1,1], at=[0, tab_y], layer='F.Fab')) # kicad_mod.append(Text(type='value', text=footprint_name, at=[0, courtyard_y2 + label_y_offset], layer='F.Fab')) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':courtyard_y1, 'bottom':courtyard_y2}, fp_name=footprint_name, text_y_inside_position=[0, tab_y]) kicad_mod.append(Text(type='value', text='PCB Edge', at=[0,actuator_y1-(ear_height-pcb_edge_gap)/2.0], size=[0.5,0.5], layer='Dwgs.User', thickness=0.08, rotation=0)) ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') if lib_by_conn_category: lib_name = configuration['lib_name_specific_function_format_string'].format(category=conn_category) else: lib_name = configuration['lib_name_format_string'].format(man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == '__main__': parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) # with pincount(s) and partnumber(s) to be generated, build them all in a nested loop for partnumber in partnumbers: for pincount in pincounts: generate_one_footprint(partnumber, pincount, configuration) ================================================ FILE: scripts/Connector/Connector_TE-Connectivity/conn_te_826576.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "826576" manufacturer = 'TE' manufacturer_lib = 'TE-Connectivity' orientation = 'V' datasheet = 'https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=826576&DocType=Customer+Drawing&DocLang=English' number_of_rows = 1 # only generate active pin counts from TE rev 7 datasheet #pins_per_row_range = range(1, 37) pins_per_row_range = [2,3,5,6,7,8,9,13,15,16,17,18,20,36] # the datasheet has an equation and a table (column 'L') for body length # the equation of pincount * 3.96 = length is wrong # the table is roughly correct based on part measurement # table is nearly pincount * 3.96 - 0.589 but capture the table exactly body_lengths = {1:3.3, 2:7.3, 3:11.3, 4:15.2, 5:19.2, 6:23.1, 7:27.1, 8:31.1, 9:35.1, 10:39, 11:43, 12:46.9, 13:50.9, 14:54.8, 15:58.8, 16:62.8, 17:66.7, 18:70.7, 19:74.7, 20:78.6, 21:82.6, 22:86.5, 23:90.5, 24:94.4, 25:98.4, 26:102.4, 27:106.3, 28:110.3, 29:114.2, 30:118.2, 31:122.2, 32:126.1, 33:130.1, 34:134, 35:138, 36:141.6} part_code = "{:s}{:s}826576-{:s}" pitch = 3.96 drill = 1.4 start_pos_x = 0 # Where should pin 1 be located? pad_size = [drill + 1, drill + 1] pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE def generate_one_footprint(pins, configuration): mpn = part_code.format(str(pins)[:1] if pins > 9 else '', '-' if pins > 9 else '', str(pins)[-1]) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_no_series_format_string'].format(man=manufacturer, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins, mounting_pad = "", pitch=pitch, orientation=orientation_str) print(footprint_name) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{:s}, {:s}, {:d} Pins ({:s}), generated with kicad-footprint-generator".format(manufacturer, mpn, pins, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) #calculate fp dimensions #B = distance between end-point pins B = (pins - 1) * pitch #A = total connector length A = body_lengths[pins] #corners x1 = -(A-B) / 2 x2 = x1 + A body_width = 6.4 y2 = body_width / 2 y1 = y2 - body_width body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() out = [ {'x': B/2, 'y': y1}, {'x': x1, 'y': y1}, {'x': x1, 'y': y2}, {'x': B/2, 'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=out, layer="F.Fab", width=configuration['fab_line_width'])) kicad_mod.append(PolygoneLine(polygone=out,x_mirror=B/2, layer="F.Fab", width=configuration['fab_line_width'])) #offset o = configuration['silk_fab_offset'] x1 -= o y1 -= o x2 += o y2 += o out = [ {'x': B/2, 'y': y1}, {'x': x1, 'y': y1}, {'x': x1, 'y': y2}, {'x': B/2, 'y': y2}, ] kicad_mod.append(PolygoneLine(polygone=out, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=out,x_mirror=B/2, layer="F.SilkS", width=configuration['silk_line_width'])) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT #generate the pads kicad_mod.append(PadArray( pincount=pins, x_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) #pin-1 marker pin_mark_width = 1 pin_mark_height = 1 pin_mask_offset = 0.5 pin = [ {'x': -pin_mark_width/2,'y': body_edge['bottom']}, {'x': 0,'y': body_edge['bottom'] - pin_mark_height}, {'x': pin_mark_width/2,'y': body_edge['bottom']}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.Fab", width=configuration['fab_line_width'])) pin = [ {'x': -pin_mark_width/2,'y': body_edge['bottom'] + pin_mark_height + pin_mask_offset}, {'x': 0,'y': body_edge['bottom'] + pin_mask_offset}, {'x': pin_mark_width/2,'y': body_edge['bottom'] + pin_mark_height + pin_mask_offset}, {'x': -pin_mark_width/2,'y': body_edge['bottom'] + pin_mark_height + pin_mask_offset} ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) ########################### CrtYd ################################# cx1 = roundToBase(bounding_box['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(bounding_box['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(bounding_box['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(bounding_box['bottom'] + configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='top') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer_lib) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pins_per_row in pins_per_row_range: generate_one_footprint(pins_per_row, configuration) ================================================ FILE: scripts/Connector/Connector_TE-Connectivity/conn_te_mate-n-lock_tht_side.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt, asin, degrees import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "MATE-N-LOK" series_long = 'Mini-Universal MATE-N-LOK' man_lib = 'TE-Connectivity' man_short_fp_name = 'TE' orientation = 'H' datasheet = "http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=82181_SOFTSHELL_HIGH_DENSITY&DocType=CS&DocLang=EN" #Molex part number #n = number of circuits per row variant_params = { 'in_line':{ 'pins_per_row_range': [1,2,3], 'number_of_rows': 1, 'style': 'in_line', 'number_pegs': 1, 'peg_from_center': 0, 'part_code': { 1: '1-794374-x', 2: '1-770966-x', 3: '1-770967-x' } }, 'dual1':{ 'pins_per_row_range': range(2,7), 'number_of_rows': 2, 'style': 'dual_row', 'number_pegs': 1, 'peg_from_center': 0, 'part_code': { 4: '1-770968-x', 6: '1-770969-x', 8: '1-770970-x', 10: '1-770971-x', 12: '1-770972-x' } }, 'dual2':{ 'pins_per_row_range': [7,9], 'number_of_rows': 2, 'style': 'dual_row', 'number_pegs': 2, 'peg_from_center': 8.28, 'part_code': { 14: '1-770973-x', 18: '1-794105-x' } }, 'dual3':{ 'pins_per_row_range': [8,10,12], 'number_of_rows': 2, 'style': 'dual_row', 'number_pegs': 2, 'peg_from_center': 10.38, 'part_code': { 16: '1-770974-x', 20: '1-794106-x', 24: '1-794108-x' } }, 'dual4':{ 'pins_per_row_range': [11], 'number_of_rows': 2, 'style': 'dual_row', 'number_pegs': 2, 'peg_from_center': 12.42, 'part_code': { 22: '1-794107-x' } }, } pitch = 4.14 drill = 1.4 pad_to_pad_clearance = 1.5 max_annular_ring = 0.95 min_annular_ring = 0.15 row = 4.14 peg_drill = 3.86 peg_to_nearest_pin = 7.34 width = 12.7 peg_to_body_right = 6.86 def generate_one_footprint(pins_per_row, variant_param, configuration): silk_pad_off = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 off = configuration['silk_fab_offset'] number_of_rows = variant_param['number_of_rows'] pad_size = [row - pad_to_pad_clearance, pitch - pad_to_pad_clearance] if number_of_rows == 1: pad_size[0] = drill + 2*max_annular_ring if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape = Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE first_to_last_pad_y = (pins_per_row-1)*pitch first_to_last_pad_x = (number_of_rows-1)*row center_y = first_to_last_pad_y/2 peg_x = (number_of_rows-1)*row + peg_to_nearest_pin peg_pos = [[peg_x, center_y + variant_param['peg_from_center']]] if variant_param['number_pegs'] == 2: peg_pos.append([peg_x, center_y - variant_param['peg_from_center']]) mpn = variant_param['part_code'][pins_per_row*number_of_rows].format(n=pins_per_row*2) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=man_short_fp_name, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format( series_long, mpn, pins_per_row, datasheet)) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=man_short_fp_name, entry=configuration['entry_direction'][orientation]) kicad_mod.setTags(tags) x2 = peg_x + peg_to_body_right x1 = x2 - width body_lenght = 5.72+first_to_last_pad_y y1 = -(body_lenght - first_to_last_pad_y)/2 y2 = y1 + body_lenght #calculate fp dimensions body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = body_edge.copy() bounding_box['left'] = -pad_size[0]/2 #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(number_of_rows): initial = row_idx*pins_per_row + 1 kicad_mod.append(PadArray( pincount=pins_per_row, initial=initial, start=[row_idx*row, 0], y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) for peg in peg_pos: kicad_mod.append(Pad(at=peg, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab',width=configuration['fab_line_width'])) dx = body_edge['left'] - off - (number_of_rows-1)*row - (pad_size[0] - pad_size[1])/2 if dx < (pad_size[1]/2 + silk_pad_off): dy = sqrt((pad_size[1]/2 + silk_pad_off)**2-dx**2) else: dy = 0 dy_rect = pad_size[1]/2 + silk_pad_off top_silk_pad = -dy if number_of_rows == 2 else -dy_rect bottom_silk_pad = (first_to_last_pad_y + dy) if pins_per_row > 1 else dy_rect silk_poly = [ {'x': body_edge['left']-off,'y': top_silk_pad}, {'x': body_edge['left']-off,'y': body_edge['top']-off}, {'x': body_edge['right']+off,'y': body_edge['top']-off}, {'x': body_edge['right']+off,'y': body_edge['bottom']+off}, {'x': body_edge['left']-off,'y': body_edge['bottom']+off}, {'x': body_edge['left']-off,'y': bottom_silk_pad}, ] kicad_mod.append(PolygoneLine(polygone=silk_poly, layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins_per_row-1): yt = i*pitch + (dy if number_of_rows == 2 or i > 1 else dy_rect) yb = (i+1)*pitch - dy kicad_mod.append(Line( start=[body_edge['left']-off, yt], end=[body_edge['left']-off, yb], layer='F.SilkS', width=configuration['silk_line_width'])) O = silk_pad_off + 0.2 pin = [ {'x': 0,'y': -pad_size[1]/2 - O}, {'x': -pad_size[0]/2 - O,'y': -pad_size[1]/2 - O}, {'x': -pad_size[0]/2 - O,'y': 0}, ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=man_lib) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: variant_param = variant_params[variant] for pins_per_row in variant_param['pins_per_row_range']: generate_one_footprint(pins_per_row, variant_param, configuration) ================================================ FILE: scripts/Connector/Connector_TE-Connectivity/conn_te_mate-n-lock_tht_top.py ================================================ #!/usr/bin/env python3 ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt, asin, degrees import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields draw_inner_details = False series = "MATE-N-LOK" series_long = 'Mini-Universal MATE-N-LOK' man_lib = 'TE-Connectivity' man_short_fp_name = 'TE' orientation = 'V' datasheet = "http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=82181_SOFTSHELL_HIGH_DENSITY&DocType=CS&DocLang=EN" #Molex part number #n = number of circuits per row variant_params = { 'in_line':{ 'pins_per_row_range': [2,3], 'number_of_rows': 1, 'style': 'in_line', 'number_pegs': 1, 'width': 5.58, 'part_code': { 2: '1-770866-x', 3: '1-770870-x' } }, 'dual1':{ 'pins_per_row_range': range(2,7), 'number_of_rows': 2, 'style': 'dual_row', 'number_pegs': 1, 'width': 9.83, 'part_code': { 4: '1-770874-x', 6: '1-770875-x', 8: '1-794073-x', 10: '1-770858-x', 12: '1-770621-x' } }, 'dual2':{ 'pins_per_row_range': range(7,13), 'number_of_rows': 2, 'style': 'dual_row', 'number_pegs': 2, 'width': 9.83, 'part_code': { 14: '1-794067-x', 16: '1-794068-x', 18: '1-794069-x', 20: '1-794070-x', 22: '1-794071-x', 24: '1-794072-x' } }, 'matrix':{ 'pins_per_row_range': [3,4,5], 'number_of_rows': 3, 'style': 'matrix', 'number_pegs': 1, 'width': 13.97, 'part_code': { 9: '1-770182-x', 12: '1-770186-x', 15: '1-770190-x' } }, } pitch = 4.14 drill = 1.4 pad_to_pad_clearance = 1.5 max_annular_ring = 0.95 min_annular_ring = 0.15 row = 4.14 peg_drill = 3.18 peg_to_nearest_pin = 4.44 def generate_one_footprint(pins_per_row, variant_param, configuration): silk_pad_off = configuration['silk_pad_clearance']+configuration['silk_line_width']/2 off = configuration['silk_fab_offset'] number_of_rows = variant_param['number_of_rows'] pad_size = [row - pad_to_pad_clearance, pitch - pad_to_pad_clearance] if number_of_rows == 1: pad_size[0] = drill + 2*max_annular_ring if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring if pad_size[1] - drill < 2*min_annular_ring: pad_size[1] = drill + 2*min_annular_ring if pad_size[1] - drill > 2*max_annular_ring: pad_size[1] = drill + 2*max_annular_ring pad_shape = Pad.SHAPE_OVAL if pad_size[0] == pad_size[1]: pad_shape = Pad.SHAPE_CIRCLE first_to_last_pad_y = (pins_per_row-1)*pitch first_to_last_pad_x = (number_of_rows-1)*row peg_pos = [[0, -peg_to_nearest_pin if variant_param['style'] != 'in_line' else (first_to_last_pad_y + peg_to_nearest_pin)]] if variant_param['number_pegs'] == 2: peg_pos.append([0, first_to_last_pad_y + peg_to_nearest_pin]) mpn = variant_param['part_code'][pins_per_row*number_of_rows].format(n=pins_per_row*2) orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=man_short_fp_name, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pins_per_row, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, old mpn/engineering number: {:s}, {:d} Pins per row ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format( series_long, mpn, pins_per_row, datasheet)) tags = configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=man_short_fp_name, entry=configuration['entry_direction'][orientation]) kicad_mod.setTags(tags) x1 = -(variant_param['width']-first_to_last_pad_x)/2 x2 = x1 + variant_param['width'] body_lenght = (9.83-pitch)+first_to_last_pad_y y1 = -(body_lenght - first_to_last_pad_y)/2 y2 = y1 + body_lenght peg_predrusion = 2.591 # from 3d model peg_d = 3.94 # from 3d model, rounded peg_from_body = 0.66 # from 3d model peg_conn_w = 1.6 # from 3d model, rounded stabalizer_width = 2.54 # from 3d model stabalizer_len = 2.591 # from 3d model TW = 3 # from 3d model, rounded TL = 1.3 # from 3d model, rounded BW = 1.14 # from 3d model, rounded BL = 0.76 # from 3d model, rounded #calculate fp dimensions body_edge={ 'left':x1, 'right':x2, 'bottom':y2, 'top': y1 } bounding_box = {} if variant_param['style'] != 'in_line': bounding_box['top'] = peg_pos[0][1]-peg_drill/2 bounding_box['left'] = body_edge['left'] - TL bounding_box['right'] = body_edge['right'] + BL if variant_param['number_pegs'] == 2: bounding_box['bottom'] = peg_pos[1][1]+peg_drill/2 else: bounding_box['bottom'] = body_edge['bottom'] + peg_predrusion else: bounding_box['bottom'] = peg_pos[0][1]+peg_drill/2 bounding_box['top'] = body_edge['top'] - TL bounding_box['left'] = body_edge['left'] - BL bounding_box['right'] = body_edge['right'] #generate the pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for row_idx in range(variant_param['number_of_rows']): initial = row_idx*pins_per_row + 1 kicad_mod.append(PadArray( pincount=pins_per_row, initial=initial, start=[row_idx*row, 0], y_spacing=pitch, type=Pad.TYPE_THT, shape=pad_shape, size=pad_size, drill=drill, layers=Pad.LAYERS_THT, **optional_pad_params)) for peg in peg_pos: kicad_mod.append(Pad(at=peg, type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=peg_drill, drill=peg_drill, layers=Pad.LAYERS_NPTH)) #draw the outline of the shape kicad_mod.append(RectLine(start=[x1,y1],end=[x2,y2], layer='F.Fab',width=configuration['fab_line_width'])) dy = peg_to_nearest_pin + body_edge['top'] - off if dy < (peg_drill/2 + silk_pad_off): dx = sqrt((peg_drill/2 + silk_pad_off)**2-dy**2) else: dx = 0 sl_poly=[ {'x': 0, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['top']-off}, {'x': body_edge['left']-off, 'y': body_edge['bottom']+off}, {'x': 0, 'y': body_edge['bottom']+off}, ] sr_poly=[ {'x': 0, 'y': body_edge['top']-off}, {'x': body_edge['right']+off, 'y': body_edge['top']-off}, {'x': body_edge['right']+off, 'y': body_edge['bottom']+off}, {'x': 0, 'y': body_edge['bottom']+off}, ] if variant_param['style'] == 'in_line' or variant_param['number_pegs'] == 2: sl_poly[3]['x']=-dx sr_poly[3]['x']=dx if variant_param['style'] != 'in_line': sl_poly[0]['x']=-dx sr_poly[0]['x']=dx kicad_mod.append(PolygoneLine(polygone=sl_poly, layer='F.SilkS', width=configuration['silk_line_width'])) kicad_mod.append(PolygoneLine(polygone=sr_poly, layer='F.SilkS', width=configuration['silk_line_width'])) def peg_outline(kicad_mod, center_y): edge = body_edge['top'] if center_y < 0 else body_edge['bottom'] dir = -1 if center_y < 0 else 1 sy=edge + dir*peg_from_body y3 = edge +dir*peg_predrusion kicad_mod.append(Line( start=[peg_conn_w/2, edge], end=[peg_conn_w/2, sy], layer='F.Fab',width=configuration['fab_line_width'] )) kicad_mod.append(Line( start=[-peg_conn_w/2, edge], end=[-peg_conn_w/2, sy], layer='F.Fab',width=configuration['fab_line_width'] )) dy = center_y - sy sx = sqrt((peg_d/2)**2-dy**2) dy2 = y3 - center_y ex = sqrt((peg_d/2)**2-dy2**2) a1 = degrees(asin(abs(dy2)/(peg_d/2))) a2 = degrees(asin(abs(dy)/(peg_d/2))) a = a1+a2 kicad_mod.append(Line( start=[sx, sy], end=[-sx, sy], layer='F.Fab',width=configuration['fab_line_width'] )) kicad_mod.append(Line( start=[ex, y3], end=[-ex, y3], layer='F.Fab',width=configuration['fab_line_width'] )) kicad_mod.append(Arc(center=[0,center_y], start=[sx,sy], angle=dir*a, layer='F.Fab', width=configuration['fab_line_width'])) kicad_mod.append(Arc(center=[0,center_y], start=[-sx,sy], angle=-a*dir, layer='F.Fab', width=configuration['fab_line_width'])) # #draw the outline of the tab if variant_param['style'] == 'in_line': tab_poly = [ {'x': -TW/2,'y': body_edge['top']}, {'x': -TW/2,'y': body_edge['top']-TL}, {'x': TW/2,'y': body_edge['top']-TL}, {'x': TW/2,'y': body_edge['top']}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.Fab', width=configuration['fab_line_width'])) tab_poly = [ {'x': -TW/2-off,'y': body_edge['top']-off}, {'x': -TW/2-off,'y': body_edge['top']-TL-off}, {'x': TW/2+off,'y': body_edge['top']-TL-off}, {'x': TW/2+off,'y': body_edge['top']-off}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.SilkS', width=configuration['silk_line_width'])) b_poly = [ {'x': body_edge['left'],'y': body_edge['top']}, {'x': body_edge['left']-BL,'y': body_edge['top']}, {'x': body_edge['left']-BL,'y': body_edge['top']+BW}, {'x': body_edge['left'],'y': body_edge['top']+BW}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['left']-off,'y': body_edge['top']-off}, {'x': body_edge['left']-BL-off,'y': body_edge['top']-off}, {'x': body_edge['left']-BL-off,'y': body_edge['top']+BW+off}, {'x': body_edge['left']-off,'y': body_edge['top']+BW+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins_per_row): yc = i*pitch+pitch/2 b_poly = [ {'x': body_edge['left'],'y': yc - BW/2}, {'x': body_edge['left']-BL,'y': yc - BW/2}, {'x': body_edge['left']-BL,'y': yc + BW/2}, {'x': body_edge['left'],'y': yc + BW/2}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['left']-off,'y': yc - BW/2-off}, {'x': body_edge['left']-BL-off,'y': yc - BW/2-off}, {'x': body_edge['left']-BL-off,'y': yc + BW/2+off}, {'x': body_edge['left']-off,'y': yc + BW/2+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) else: cy = first_to_last_pad_y/2 tab_poly = [ {'x': body_edge['left'],'y': cy-TW/2}, {'x': body_edge['left']-TL,'y': cy-TW/2}, {'x': body_edge['left']-TL,'y': cy+TW/2}, {'x': body_edge['left'],'y': cy+TW/2}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.Fab', width=configuration['fab_line_width'])) tab_poly = [ {'x': body_edge['left']-off,'y': cy-TW/2-off}, {'x': body_edge['left']-TL-off,'y': cy-TW/2-off}, {'x': body_edge['left']-TL-off,'y': cy+TW/2+off}, {'x': body_edge['left']-off,'y': cy+TW/2+off}, ] kicad_mod.append(PolygoneLine(polygone=tab_poly, layer='F.SilkS', width=configuration['silk_line_width'])) b_poly = [ {'x': body_edge['right'],'y': body_edge['top']}, {'x': body_edge['right']+BL,'y': body_edge['top']}, {'x': body_edge['right']+BL,'y': body_edge['top']+BW}, {'x': body_edge['right'],'y': body_edge['top']+BW}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['right']+off,'y': body_edge['top']-off}, {'x': body_edge['right']+BL+off,'y': body_edge['top']-off}, {'x': body_edge['right']+BL+off,'y': body_edge['top']+BW+off}, {'x': body_edge['right']+off,'y': body_edge['top']+BW+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) if len(peg_pos) == 1: center_stabalizer = (number_of_rows-1)*row stab_x1 = center_stabalizer - stabalizer_width/2 stab_x2 = center_stabalizer + stabalizer_width/2 stab_y1 = body_edge['bottom'] + stabalizer_len stab_poly = [ {'x': stab_x1,'y': body_edge['bottom']}, {'x': stab_x1,'y': stab_y1}, {'x': stab_x2,'y': stab_y1}, {'x': stab_x2,'y': body_edge['bottom']} ] kicad_mod.append(PolygoneLine(polygone=stab_poly, layer='F.Fab', width=configuration['fab_line_width'])) stab_poly = [ {'x': stab_x1-off,'y': body_edge['bottom']+off}, {'x': stab_x1-off,'y': stab_y1+off}, {'x': stab_x2+off,'y': stab_y1+off}, {'x': stab_x2+off,'y': body_edge['bottom']+off} ] kicad_mod.append(PolygoneLine(polygone=stab_poly, layer='F.SilkS', width=configuration['silk_line_width'])) for i in range(pins_per_row): yc = i*pitch+pitch/2 b_poly = [ {'x': body_edge['right'],'y': yc - BW/2}, {'x': body_edge['right']+BL,'y': yc - BW/2}, {'x': body_edge['right']+BL,'y': yc + BW/2}, {'x': body_edge['right'],'y': yc + BW/2}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.Fab', width=configuration['fab_line_width'])) b_poly = [ {'x': body_edge['right']+off,'y': yc - BW/2-off}, {'x': body_edge['right']+BL+off,'y': yc - BW/2-off}, {'x': body_edge['right']+BL+off,'y': yc + BW/2+off}, {'x': body_edge['right']+off,'y': yc + BW/2+off}, ] kicad_mod.append(PolygoneLine(polygone=b_poly, layer='F.SilkS', width=configuration['silk_line_width'])) for peg in peg_pos: peg_outline(kicad_mod, peg[1]) if variant_param['style'] != 'in_line': L = 2.5 O = off + 0.3 dy = peg_to_nearest_pin + body_edge['top'] - O if dy < (peg_drill/2 + silk_pad_off): dx = sqrt((peg_drill/2 + silk_pad_off)**2-dy**2) pin = [ {'x': -dx,'y': body_edge['top'] - O}, {'x': body_edge['left'] - O,'y': body_edge['top'] - O}, {'x': body_edge['left'] - O,'y': body_edge['top'] + L} ] else: sl = 0.6 xs = body_edge['left']-(off + 0.3) pin = [ {'x': xs,'y': 0}, {'x': xs - sl/sqrt(2),'y': sl/2}, {'x': xs - sl/sqrt(2),'y': -sl/2}, {'x': xs,'y': 0} ] kicad_mod.append(PolygoneLine(polygone=pin, layer="F.SilkS", width=configuration['silk_line_width'])) sl = 2 pin = [ {'x': body_edge['left'],'y': -sl/2}, {'x': body_edge['left'] +sl/sqrt(2),'y': 0}, {'x': body_edge['left'],'y': sl/2} ] kicad_mod.append(PolygoneLine(polygone=pin, width=configuration['fab_line_width'], layer='F.Fab')) ########################### CrtYd ################################# CrtYd_offset = configuration['courtyard_offset']['connector'] CrtYd_grid = configuration['courtyard_grid'] cx1 = roundToBase(bounding_box['left'] - CrtYd_offset, CrtYd_grid) cy1 = roundToBase(bounding_box['top'] - CrtYd_offset, CrtYd_grid) cx2 = roundToBase(bounding_box['right'] + CrtYd_offset, CrtYd_grid) cy2 = roundToBase(bounding_box['bottom'] + CrtYd_offset, CrtYd_grid) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='right') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=man_lib) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for variant in variant_params: variant_param = variant_params[variant] for pins_per_row in variant_param['pins_per_row_range']: generate_one_footprint(pins_per_row, variant_param, configuration) ================================================ FILE: scripts/Connector/Connector_TE-Connectivity/helpers.py ================================================ def roundToBase(value, base): if base == 0: return value return round(value/base) * base ================================================ FILE: scripts/Connector/Connector_Wago/conn_wago_734_horizontal.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "" series_long = '734 Male header (for PCBs); Angled solder pin 1 x 1 mm' manufacturer = 'Wago' orientation = 'H' number_of_rows = 1 datasheet = 'http://www.farnell.com/datasheets/2157639.pdf' pinrange= [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 24] # Connector voltage ratings: # Rated voltage (III / 3) [V] 160 V # Rated impulse voltage (III / 3) [kV] 2.5 kV # Rated voltage (III/2) [V] 160 V # Rated impulse voltage (III / 2) [kV] 2.5 kV # Rated voltage (II / 2) [V] 320 V # Rated impulse voltage (II / 2) [kV] 2.5 kV # VDE 0110-1/4.97 2.5kV -> 1.5mm clearance pad_to_pad_clearance = 1.5 pitch = 3.5 drill = 1.6 # square pins:1mm -> touching circle: √(2)mm ~ 1.4mm -> minimum drill accourding to KLC: 1.6mm start_pos_x = 0 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE mpn_format = '734-1{n_plus_60:02d}' def generate_one_footprint(pincount, configuration): pad_silk_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 mpn = mpn_format.format(n_plus_60=pincount+60) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__", '_') kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, {:s} , {:d} Pins ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # calculate working values end_pos_x = (pincount-1) * pitch centre_x = (end_pos_x - start_pos_x) / 2.0 nudge = configuration['silk_fab_offset'] silk_w = configuration['silk_line_width'] fab_w = configuration['fab_line_width'] body_edge={ 'left':start_pos_x - 2.8, 'right':end_pos_x + 3.1, 'bottom':9.3 } body_edge['top'] = body_edge['bottom']-10.3 # create pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[start_pos_x, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) # create fab outline kicad_mod.append(RectLine(start=[body_edge['left'], body_edge['top']], end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=fab_w)) # create silkscreen x1 = start_pos_x -pad_size[0]/2 - pad_silk_off xn = end_pos_x + pad_size[0]/2 + pad_silk_off kicad_mod.append(PolygoneLine( polygone=[ {'x': x1, 'y': body_edge['top']-nudge}, {'x': body_edge['left']-nudge, 'y': body_edge['top']-nudge}, {'x': body_edge['left']-nudge, 'y': body_edge['bottom']+nudge}, {'x': body_edge['right']+nudge, 'y': body_edge['bottom']+nudge}, {'x': body_edge['right']+nudge, 'y': body_edge['top']-nudge}, {'x': xn, 'y': body_edge['top']-nudge} ], layer='F.SilkS', width=silk_w)) for i in range(pincount-1): xl = start_pos_x + i*pitch + pad_size[0]/2 + pad_silk_off xr = start_pos_x + (i+1)*pitch - pad_size[0]/2 - pad_silk_off kicad_mod.append(Line( start=[xl, body_edge['top']-nudge], end=[xr, body_edge['top']-nudge], layer='F.SilkS', width=silk_w)) p1s_off = configuration['silk_fab_offset'] + 0.3 p1s_L = 2 # pin 1 markers kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] + p1s_L}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] - p1s_off}, {'x': x1, 'y': body_edge['top'] - p1s_off} ], layer='F.SilkS', width=silk_w)) sl = 1 poly_pin1_marker = [ {'y': body_edge['top'], 'x': -sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': 0}, {'y': body_edge['top'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=fab_w)) ########################### CrtYd ################################# cx1 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(body_edge['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(body_edge['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pinrange: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Wago/conn_wago_734_vertical.py ================================================ #!/usr/bin/env python3 # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from math import sqrt import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "" series_long = '734 Male header (for PCBs); Straight solder pin 1 x 1 mm' manufacturer = 'Wago' orientation = 'V' number_of_rows = 1 datasheet = 'http://www.farnell.com/datasheets/2157639.pdf' pinrange= [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 24] # Connector voltage ratings: # Rated voltage (III / 3) [V] 160 V # Rated impulse voltage (III / 3) [kV] 2.5 kV # Rated voltage (III/2) [V] 160 V # Rated impulse voltage (III / 2) [kV] 2.5 kV # Rated voltage (II / 2) [V] 320 V # Rated impulse voltage (II / 2) [kV] 2.5 kV # VDE 0110-1/4.97 2.5kV -> 1.5mm clearance pad_to_pad_clearance = 1.5 pitch = 3.5 drill = 1.6 # square pins:1mm -> touching circle: √(2)mm ~ 1.4mm -> minimum drill accourding to KLC: 1.6mm start_pos_x = 0 max_annular_ring = 0.5 min_annular_ring = 0.15 pad_size = [pitch - pad_to_pad_clearance, drill + 2*max_annular_ring] if pad_size[0] - drill < 2*min_annular_ring: pad_size[0] = drill + 2*min_annular_ring if pad_size[0] - drill > 2*max_annular_ring: pad_size[0] = drill + 2*max_annular_ring pad_shape=Pad.SHAPE_OVAL if pad_size[1] == pad_size[0]: pad_shape=Pad.SHAPE_CIRCLE mpn_format = '734-1{n_plus_30:02d}' def generate_one_footprint(pincount, configuration): mpn = mpn_format.format(n_plus_30=pincount+30) # handle arguments orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) footprint_name = footprint_name.replace("__", '_') kicad_mod = Footprint(footprint_name) descr_format_str = "Molex {:s}, {:s} , {:d} Pins ({:s}), generated with kicad-footprint-generator" kicad_mod.setDescription(descr_format_str.format(series_long, mpn, pincount, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) # calculate working values end_pos_x = (pincount-1) * pitch centre_x = (end_pos_x - start_pos_x) / 2.0 nudge = configuration['silk_fab_offset'] silk_w = configuration['silk_line_width'] fab_w = configuration['fab_line_width'] body_edge={ 'left':start_pos_x - 2.8, 'right':end_pos_x + 3.1, 'bottom':4.35 } body_edge['top'] = body_edge['bottom']-8.5 # create pads optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[start_pos_x, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) # create fab outline kicad_mod.append(RectLine(start=[body_edge['left'], body_edge['top']],\ end=[body_edge['right'], body_edge['bottom']], layer='F.Fab', width=fab_w)) # create silkscreen kicad_mod.append(RectLine(start=[body_edge['left']-nudge, body_edge['top']-nudge],\ end=[body_edge['right']+nudge, body_edge['bottom']+nudge], layer='F.SilkS', width=silk_w)) # Inner silk: T = 0.5 w1 = body_edge['right'] - end_pos_x - T y1 = body_edge['top'] + 1.5 y2 = body_edge['bottom'] - 1.5 y3 = body_edge['bottom'] - T x1 = body_edge['left'] + T x2 = start_pos_x x3 = x2 + w1 x4 = end_pos_x x5 = x4 + w1 poly_inside = [ {'x': x1, 'y':y1}, {'x': x1, 'y':y2}, {'x': x2, 'y':y2}, {'x': x2, 'y':y3}, {'x': x3, 'y':y3}, {'x': x3, 'y':y2}, {'x': x4, 'y':y2}, {'x': x4, 'y':y3}, {'x': x5, 'y':y3}, {'x': x5, 'y':y1}, {'x': x1, 'y':y1} ] kicad_mod.append(PolygoneLine(polygone=poly_inside, layer='F.SilkS', width=silk_w)) p1s_off = configuration['silk_fab_offset'] + 0.3 p1s_L = 2 # pin 1 markers kicad_mod.append(PolygoneLine( polygone=[ {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] + p1s_L}, {'x': body_edge['left'] - p1s_off, 'y': body_edge['top'] - p1s_off}, {'x': body_edge['left'] + p1s_L, 'y': body_edge['top'] - p1s_off} ], layer='F.SilkS', width=silk_w)) sl = 1 poly_pin1_marker = [ {'y': body_edge['top'], 'x': -sl/2}, {'y': body_edge['top'] + sl/sqrt(2), 'x': 0}, {'y': body_edge['top'], 'x': sl/2} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=fab_w)) ########################### CrtYd ################################# cx1 = roundToBase(body_edge['left']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(body_edge['top']-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(body_edge['right']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(body_edge['bottom']+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position='bottom') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in pinrange: generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/Connector_Wago/helpers.py ================================================ def roundToBase(value, base): if base == 0: return value return round(value/base) * base ================================================ FILE: scripts/Connector/Connector_Wire/Research/sources.md ================================================ - https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf - http://www.farnell.com/datasheets/1772974.pdf - http://www.farnell.com/datasheets/2818581.pdf - http://www.farnell.com/datasheets/1872097.pdf - http://www.farnell.com/datasheets/2198328.pdf ================================================ FILE: scripts/Connector/Connector_Wire/solder_wire_tht.py ================================================ import sys import os import argparse import yaml import math from copy import deepcopy # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) from KicadModTree import * # NOQA from KicadModTree.util.geometric_util import geometricLine, geometricCircle from KicadModTree.util.paramUtil import round_to # load parent path of tools sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) from footprint_text_fields import addTextFields DEFAULT_MIN_PAD_DRILL_INC = 0.2 DEFAULT_PAD_DRILL_INC_FACTOR = 1.25 DEFAULT_RELIEF_DRILL_INC = 0.5 FOOTPRINT_TYPES = { 'plain':{ 'name': '', 'description': '', 'tag': '', 'relief_count': 0 }, 'relief':{ 'name': '_Relief', 'description': ' with feed through strain relief', 'tag': ' strain-relief', 'relief_count': 1 }, 'relief2x':{ 'name': '_Relief2x', 'description': ' with double feed through strain relief', 'tag': ' double-strain-relief', 'relief_count': 2 } } def bend_radius(wire_def): return wire_def['outer_diameter'] * 3 def fp_name_gen(wire_def, fp_type, pincount, pitch): if 'area' in wire_def: size_code = '{:g}sqmm'.format(wire_def['area']) return 'SolderWire-{}_1x{:02d}{}_D{:g}mm_OD{:g}mm{}'.format( size_code, pincount, '' if pincount == 1 else '_P{:g}mm'.format(pitch), wire_def['diameter'], wire_def['outer_diameter'], fp_type ) def description_gen(wire_def, fp_type, pincount, pitch): if 'area' in wire_def: size_code = '{:g} mm²'.format(wire_def['area']) d1 = 'for a single {size:s} wire' if pincount == 1 else 'for {count:d} times {size:s} wires' return ( 'Soldered wire connection{}, {}, ' '{} insulation, ' 'conductor diameter {:g}mm, outer diameter {:g}mm, ' 'size source {}, ' 'bend radius 3 times outer diameter, ' 'generated with kicad-footprint-generator' .format( fp_type, d1.format(count=pincount, size=size_code), wire_def['insulation'], wire_def['diameter'], wire_def['outer_diameter'], wire_def['source'] ) ) def tag_gen(wire_def, fp_type, pincount, pitch): if 'area' in wire_def: size_code = '{:g}sqmm'.format(wire_def['area']) return 'connector wire {}{}'.format(size_code, fp_type) def make_fp(wire_def, fp_type, pincount, configuration): crtyd_off= configuration['courtyard_offset']['connector'] silk_pad_off = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 pad_drill = max(wire_def['diameter'] + configuration['min_pad_drill_inc'], wire_def['diameter'] * configuration['pad_drill_factor']) pad_drill = round_to(pad_drill, 0.05) pad_size = max(pad_drill + 1, wire_def['outer_diameter']) npth_drill = wire_def['outer_diameter'] + configuration['relief_drill_inc'] npth_drill = round_to(npth_drill, 0.05) npth_offset = bend_radius(wire_def)*2 pitch = max(2*wire_def['outer_diameter'], pad_size+2, npth_drill+2) fp_name = fp_name_gen(wire_def, fp_type['name'], pincount, pitch) kicad_mod = Footprint(fp_name) kicad_mod.setDescription(description_gen(wire_def, fp_type['description'], pincount, pitch)) kicad_mod.setTags(tag_gen(wire_def, fp_type['tag'], pincount, pitch)) kicad_mod.setAttribute('virtual') prototype = Translation(0, 0) kicad_mod.append(PadArray( initial=1, increment=1, pincount=pincount, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, start=(0, 0), spacing=(pitch, 0), drill=pad_drill, size=pad_size, radius_ratio=0.25, maximum_radius=0.25, layers=Pad.LAYERS_THT )) for i in range(fp_type['relief_count']): prototype.append(Pad( number='', type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=(0, (i+1)*npth_offset), drill=npth_drill, size=npth_drill, layers=Pad.LAYERS_NPTH )) ######################### Fab Graphic ############################### for i in range(fp_type['relief_count']+1): prototype.append(Circle( center=(0, i*npth_offset), radius=wire_def['outer_diameter']/2, layer='F.Fab', width=configuration['fab_line_width'] )) # wire on top side if fp_type['relief_count']>0: for i in range((fp_type['relief_count']+1)//2): sy = 2*i * npth_offset ey = (2*i+1) * npth_offset prototype.append(Line( start=(-wire_def['outer_diameter']/2, sy), end=(-wire_def['outer_diameter']/2, ey), layer='F.Fab', width=configuration['fab_line_width'] )) prototype.append(Line( start=(wire_def['outer_diameter']/2, sy), end=(wire_def['outer_diameter']/2, ey), layer='F.Fab', width=configuration['fab_line_width'] )) if fp_type['relief_count']>1: for i in range(fp_type['relief_count']): prototype.append(Circle( center=(0, (i+1)*npth_offset), radius=wire_def['outer_diameter']/2, layer='B.Fab', width=configuration['fab_line_width'] )) for i in range((fp_type['relief_count'])//2): sy = (2*i+1) * npth_offset ey = (2*i+2) * npth_offset prototype.append(Line( start=(-wire_def['outer_diameter']/2, sy), end=(-wire_def['outer_diameter']/2, ey), layer='B.Fab', width=configuration['fab_line_width'] )) prototype.append(Line( start=(wire_def['outer_diameter']/2, sy), end=(wire_def['outer_diameter']/2, ey), layer='B.Fab', width=configuration['fab_line_width'] )) ######################### Silk Graphic ############################## silk_x = wire_def['outer_diameter']/2 + configuration['silk_fab_offset'] silk_helper_line = geometricLine(start=(silk_x, 0), end=(silk_x, npth_offset))\ .cut(geometricCircle(center=(0,0), radius=(npth_drill/2 + silk_pad_off)))[1] silk_y_rel_npth = silk_helper_line.start_pos['x'] if fp_type['relief_count']>0: if silk_x > pad_size/2 + silk_pad_off: top = 0 else: top = pad_size/2 + silk_pad_off bottom = npth_offset - silk_y_rel_npth prototype.append(Line( start=(silk_x, top), end=(silk_x, bottom), layer='F.SilkS', width=configuration['silk_line_width'] )) prototype.append(Line( start=(-silk_x, top), end=(-silk_x, bottom), layer='F.SilkS', width=configuration['silk_line_width'] )) if fp_type['relief_count']>1: for i in range(fp_type['relief_count']-1): layer = 'F.SilkS' if i%2 == 1 else 'B.SilkS' top = (i+1)*npth_offset + silk_y_rel_npth bottom = (i+2)*npth_offset - silk_y_rel_npth prototype.append(Line( start=(silk_x, top), end=(silk_x, bottom), layer=layer, width=configuration['silk_line_width'] )) prototype.append(Line( start=(-silk_x, top), end=(-silk_x, bottom), layer=layer, width=configuration['silk_line_width'] )) ########################## Courtyard ################################ crtyd_x = max(pad_size, npth_drill)/2 + crtyd_off crtyd_top = -max(pad_size, wire_def['outer_diameter'])/2 - crtyd_off crtyd_top_main = crtyd_top if fp_type['relief_count'] == 0: crtyd_bottom = -crtyd_top crtyd_bottom_main = crtyd_bottom else: crtyd_bottom = npth_offset + npth_drill/2 + crtyd_off crtyd_bottom_main = npth_offset*fp_type['relief_count'] + npth_drill/2 + crtyd_off layer = 'F.CrtYd' prototype.append(RectLine( start=Vector2D(-crtyd_x, crtyd_top).round_to(configuration['courtyard_grid']), end=Vector2D(crtyd_x, crtyd_bottom).round_to(configuration['courtyard_grid']), layer=layer, width=configuration['courtyard_line_width'] )) if fp_type['relief_count']>0: i = fp_type['relief_count'] layer = 'B.CrtYd' if i%2 == 1 else 'F.CrtYd' crtyd_top = (i)*npth_offset - (npth_drill/2 + crtyd_off) crtyd_bottom = (i)*npth_offset + npth_drill/2 + crtyd_off prototype.append(RectLine( start=Vector2D(-crtyd_x, crtyd_top).round_to(configuration['courtyard_grid']), end=Vector2D(crtyd_x, crtyd_bottom).round_to(configuration['courtyard_grid']), layer=layer, width=configuration['courtyard_line_width'] )) if fp_type['relief_count']>1: for i in range(fp_type['relief_count']-1): layer = 'F.CrtYd' if i%2 == 1 else 'B.CrtYd' crtyd_top = (i+1)*npth_offset - (npth_drill/2 + crtyd_off) crtyd_bottom = (i+2)*npth_offset + npth_drill/2 + crtyd_off prototype.append(RectLine( start=Vector2D(-crtyd_x, crtyd_top).round_to(configuration['courtyard_grid']), end=Vector2D(crtyd_x, crtyd_bottom).round_to(configuration['courtyard_grid']), layer=layer, width=configuration['courtyard_line_width'] )) ######################### Text Fields ############################### center_x = (pincount-1)*pitch/2 y1 = -wire_def['outer_diameter']/2 y2 = wire_def['outer_diameter']/2 + (npth_offset if fp_type['relief_count'] > 0 else 0) if pincount%2 == 0 and fp_type['relief_count'] == 0: y1 = crtyd_top_main y2 = crtyd_bottom_main addTextFields( kicad_mod=kicad_mod, configuration=configuration, body_edges={ 'left':center_x - wire_def['outer_diameter']/2, 'right':center_x + wire_def['outer_diameter']/2, 'top':y1, 'bottom':y2 }, courtyard={'top':crtyd_top_main, 'bottom':crtyd_bottom_main}, fp_name=fp_name, text_y_inside_position='center', allow_rotation=True ) ##################### Output and 3d model ############################ for i in range(pincount): prototype.offset_x = i*pitch kicad_mod.append(deepcopy(prototype)) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = 'Connector_Wire' model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'\ .format(outdir=output_dir, fp_name=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) def make_for_wire(wire_def, configuration): for fp_type in FOOTPRINT_TYPES: for i in range(6): make_fp(wire_def, FOOTPRINT_TYPES[fp_type], i+1, configuration) def make_for_file(filepath, configuration): with open(filepath, 'r') as wire_definition: try: wires = yaml.safe_load(wire_definition) for w in wires: make_for_wire(wires[w], configuration) except yaml.YAMLError as exc: print(exc) if __name__ == "__main__": parser = argparse.ArgumentParser( description='Create footprints for directly soldering wires to a PCB.' ) parser.add_argument( 'wire_def', metavar='wire_def', type=str, nargs='+', help='Wire definition files' ) parser.add_argument( '--global_config', type=str, nargs='?', help='The config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml' ) parser.add_argument( '--minimum_pad_drill_oversize', type=float, default=DEFAULT_MIN_PAD_DRILL_INC, help='Determines the minimum for how much the pads PTH drill is increased compared to conductor diameter.' ) parser.add_argument( '--pad_drill_factor', type=float, default=DEFAULT_PAD_DRILL_INC_FACTOR, help='Determines the multiplicator for pad drill size compared to conductor diameter' ) parser.add_argument( '--relief_drill_oversize', type=float, default=DEFAULT_RELIEF_DRILL_INC, help='Determines how much the relief NPTH drill is increased compared to outer diameter.' ) args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) configuration['pad_drill_factor'] = args.pad_drill_factor configuration['min_pad_drill_inc'] = args.minimum_pad_drill_oversize configuration['relief_drill_inc'] = args.relief_drill_oversize for filepath in args.wire_def: make_for_file(filepath, configuration) ================================================ FILE: scripts/Connector/Connector_Wire/wire_MC_Flexivolt.yaml ================================================ "FLEXI-E_0.1": source: 'Multi-Contact FLEXI-E 0.1 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 0.1 #awg: diameter: 0.4 outer_diameter: 1 "FLEXI-E/HK_0.127": source: 'Multi-Contact FLEXI-E/HK 0.127 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 0.127 #awg: diameter: 0.48 outer_diameter: 1 "FLEXI-E_0.15": source: 'Multi-Contact FLEXI-E 0.15 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 0.15 #awg: diameter: 0.5 outer_diameter: 1.5 "FLEXI-E_0.25": source: 'Multi-Contact FLEXI-E_0.25 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 0.25 #awg: diameter: 0.65 outer_diameter: 1.7 "FLEXI-E_0.5": source: 'Multi-Contact FLEXI-E 0.5 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 0.5 #awg: diameter: 0.9 outer_diameter: 2.1 "FLEXI-E_0.75": source: 'Multi-Contact FLEXI-E 0.75 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 0.75 #awg: diameter: 1.25 outer_diameter: 2.3 "FLEXI-E_1": source: 'Multi-Contact FLEXI-E 1.0 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 1 #awg: diameter: 1.4 outer_diameter: 2.7 "FLEXI-E_1.5": source: 'Multi-Contact FLEXI-E 1.5 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 1.5 #awg: diameter: 1.7 outer_diameter: 3 "FLEXI-E_2.5": source: 'Multi-Contact FLEXI-E 2.5 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'basic' area: 2.5 #awg: diameter: 2.4 outer_diameter: 3.6 "FLEXI-2V_0.25": source: 'Multi-Contact FLEXI-2V 0.25 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'reinforced' area: 0.25 #awg: diameter: 0.65 outer_diameter: 2 "FLEXI-xV_0.5": source: 'Multi-Contact FLEXI-xV 0.5 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'reinforced' area: 0.5 #awg: diameter: 0.9 outer_diameter: 2.3 "FLEXI-xV_0.75": source: 'Multi-Contact FLEXI-xV 0.75 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'reinforced' area: 0.75 #awg: diameter: 1.25 outer_diameter: 3.5 "FLEXI-xV_1.0": source: 'Multi-Contact FLEXI-xV 1.0 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'reinforced' area: 1 #awg: diameter: 1.4 outer_diameter: 3.9 "FLEXI-xV_1.5": source: 'Multi-Contact FLEXI-xV 1.5 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'reinforced' area: 1.5 #awg: diameter: 1.7 outer_diameter: 3.9 "FLEXI-xV_2.0": source: 'Multi-Contact FLEXI-xV 2.0 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'reinforced' area: 2.0 #awg: diameter: 2.0 outer_diameter: 3.9 "FLEXI-xV_2.5": source: 'Multi-Contact FLEXI-xV 2.5 (https://ec.staubli.com/AcroFiles/Catalogues/TM_Cab-Main-11014119_(en)_hi.pdf)' insulation: 'reinforced' area: 2.5 #awg: diameter: 2.4 outer_diameter: 4.4 ================================================ FILE: scripts/Connector/Connector_Wuerth/wuerth_6480xx11622.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree import argparse import yaml from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "WR-WTB" manufacturer = 'Wuerth' orientation = 'V' number_of_rows = 1 datasheet = 'https://katalog.we-online.com/em/datasheet/6480xx11622.pdf' mpn_pattern = "6480{n:02}11622" fab_pin1_marker_type = 2 pin1_marker_offset = 0.3 pin1_marker_linelen = 1.25 drill_size = 0.87 #Datasheet: 0.7 +0.1/-0.0 => It might be better to assume 0.75 +/-0.05mm pad_to_pad_clearance = 0.8 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 pitch = 1.5 # Connector Parameters x_min = -1.5 y_min = -1.3 y_max = y_min + 3.5 def roundToBase(value, base): return round(value/base) * base def generate_one_footprint(pincount, configuration): silk_x_min = x_min - configuration['silk_fab_offset'] silk_y_min = y_min - configuration['silk_fab_offset'] silk_y_max = y_max + configuration['silk_fab_offset'] x_mid = (pincount-1)*pitch/2.0 x_max = (pincount-1)*pitch + 1.5 silk_x_max = x_max + configuration['silk_fab_offset'] # Through-hole type shrouded header, Top entry type mpn = mpn_pattern.format(n=pincount) # part number format string orientation_str = configuration['orientation_options'][orientation] footprint_name = configuration['fp_name_format_string'].format(man=manufacturer, series=series, mpn=mpn, num_rows=number_of_rows, pins_per_row=pincount, mounting_pad = "", pitch=pitch, orientation=orientation_str) kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("{:s} {:s} series connector, {:s} ({:s}), generated with kicad-footprint-generator".format(manufacturer, series, mpn, datasheet)) kicad_mod.setTags(configuration['keyword_fp_string'].format(series=series, orientation=orientation_str, man=manufacturer, entry=configuration['entry_direction'][orientation])) ########################## Fab Outline ############################### kicad_mod.append(RectLine(start=[x_min,y_min], end=[x_max,y_max], layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: poly_pin1_marker_type2 = [ {'x':-1, 'y':y_min}, {'x':0, 'y':y_min+1}, {'x':1, 'y':y_min} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) # create Silkscreen kicad_mod.append(RectLine(start=[silk_x_min,silk_y_min], end=[silk_x_max,silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) wall_thikness=0.2 if configuration['allow_silk_below_part'] == 'tht' or configuration['allow_silk_below_part'] == 'both': poly_silk_inner_outline = [ {'x':silk_x_min, 'y':-0.35}, {'x':silk_x_min+wall_thikness, 'y':-0.35}, {'x':silk_x_min+wall_thikness, 'y':silk_y_min+wall_thikness}, {'x':silk_x_max-wall_thikness, 'y':silk_y_min+wall_thikness}, {'x':silk_x_max-wall_thikness, 'y':-0.35}, {'x':silk_x_max, 'y':-0.35} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_inner_outline, layer='F.SilkS', width=configuration['silk_line_width'])) poly_silk_inner_outline = [ {'x':silk_x_min+wall_thikness, 'y':-0.35}, {'x':silk_x_min+wall_thikness, 'y':0.35}, {'x':silk_x_min, 'y':0.35} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_inner_outline, layer='F.SilkS', width=configuration['silk_line_width'])) poly_silk_inner_outline = [ {'x':silk_x_max-wall_thikness, 'y':-0.35}, {'x':silk_x_max-wall_thikness, 'y':0.35}, {'x':silk_x_max, 'y':0.35} ] kicad_mod.append(PolygoneLine(polygone=poly_silk_inner_outline, layer='F.SilkS', width=configuration['silk_line_width'])) poly_silk_inner_outline = [ {'x':silk_x_min+wall_thikness, 'y':0.35}, {'x':silk_x_min+wall_thikness, 'y':silk_y_max-wall_thikness}, {'x':silk_x_max-wall_thikness, 'y':silk_y_max-wall_thikness}, {'x':silk_x_max-wall_thikness, 'y':0.35}, ] kicad_mod.append(PolygoneLine(polygone=poly_silk_inner_outline, layer='F.SilkS', width=configuration['silk_line_width'])) poly_pin1_marker = [ {'x':silk_x_min-pin1_marker_offset+pin1_marker_linelen, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset+pin1_marker_linelen} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) ############################# CrtYd ################################## part_x_min = x_min part_x_max = x_max part_y_min = y_min part_y_max = y_max cx1 = roundToBase(part_x_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(part_y_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(part_x_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(part_y_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ############################# Pads ################################## pad_size = [pitch - pad_to_pad_clearance, drill_size + 2*pad_copper_y_solder_length] if pad_size[0] - drill_size < 2*min_annular_ring: pad_size[0] = drill_size + 2*min_annular_ring # kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, # at=[0, 0], size=pad_size, # drill=drill_size, layers=Pad.LAYERS_THT)) optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT kicad_mod.append(PadArray(initial=1, start=[0, 0], x_spacing=pitch, pincount=pincount, size=pad_size, drill=drill_size, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### text_center_y = 1.5 body_edge={'left':part_x_min, 'right':part_x_max, 'top':part_y_min, 'bottom':part_y_max} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=series, man=manufacturer) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../conn_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible for pincount in range(2,11): generate_one_footprint(pincount, configuration) ================================================ FILE: scripts/Connector/conn_config_KLCv2.yaml ================================================ fp_name_format_string: '{man:s}_{series:s}_{mpn:s}_{pins_per_row:02d}xPitch{pitch:.2f}mm_{orientation:s}' orientation_options: H: 'Horizontal' V: 'Vertical' entry_direction: H: 'top entry' V: 'side entry' #keyword_fp_string: 'connector {man:s} {series:s} {mpn:s} {entry:s} {orientation:s}' keyword_fp_string: 'connector {man:s} {series:s} {entry:s}' #lib_name_format_string: 'Conn_{man:s}_{series:s}' lib_name_format_string: 'Connectors_{man:s}' lib_name_specific_function_format_string: 'Connector_{category:s}' ================================================ FILE: scripts/Connector/conn_config_KLCv3.yaml ================================================ fp_name_format_string: '{man:s}_{series:s}_{mpn:s}_{num_rows:d}x{pins_per_row:02d}{mounting_pad:s}_P{pitch:.2f}mm_{orientation:s}' fp_name_format_string_shielded: '{man:s}_{series:s}_{mpn:s}_{num_rows:d}x{pins_per_row:02d}-{shield_pins:d}SH_P{pitch:.2f}mm_{orientation:s}' fp_name_no_series_format_string: '{man:s}_{mpn:s}_{num_rows:d}x{pins_per_row:02d}{mounting_pad:s}_P{pitch:.2f}mm_{orientation:s}' fp_name_dual_pitch_format_string: '{man:s}_{series:s}_{mpn:s}_{num_rows:d}x{pins_per_row:02d}{mounting_pad:s}_P{pitch_x:.2f}x{pitch_y:.2f}mm_{orientation:s}' fp_name_unequal_row_format_string: '{man:s}_{series:s}_{mpn:s}_{num_rows:d}Rows-{pins:02d}Pins{mounting_pad:s}_P{pitch:.2f}mm_{orientation:s}' orientation_options: H: 'Horizontal' V: 'Vertical' entry_direction: H: 'horizontal' V: 'vertical' #keyword_fp_string: 'connector {man:s} {series:s} {mpn:s} {entry:s} {orientation:s}' keyword_fp_string: 'connector {man:s} {series:s} {entry:s}' lib_name_format_string_full: 'Connector_{man:s}_{series:s}{suffix:s}' lib_name_format_string: 'Connector_{man:s}' lib_name_specific_function_format_string: 'Connector_{category:s}' mounting_pad_number: "MP" ================================================ FILE: scripts/Connector_PinSocket/canvas.py ================================================ #!/usr/bin/env python # # Generic extension module for KicadModTree in the kicad-footprint-generator framework # # This module requires the kicad-footprint-generator framework # by Thomas Pointhuber, https://github.com/pointhi/kicad-footprint-generator # # This module 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. # # This module 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # This module contains wrapper classes and methods for parts # of the KicadModTree primitives. # They provide "turtle style" drawing using relative moves in order # to simplify the math involved in calculating and keeping track of vertex coordinates. # They also introduce the concept of canvases for drawing the different layers, this # to simplify drawing and provide functionality such as transparent grid align # and method chaining. # A canvas is somewhat similar to a workplane in CadQuery which is # often used for creating KiCad 3D models. # # (C) 2017 by Terje Io, # # NOTE: # The code for the the Keepout class is loosely based on code from drawing_tools.py # Currently oval and rectangular keepout zones are respected # for horizontal and vertical lines, only basic support (bounding box only) for diagonal lines. # Arcs and circles are not yet handled. On TODO: list. # More testing needs to be done for edge cases, such as for lines inside # the bounding box but outside the keepout area proper. # # 2017-11-25 import sys import os import math sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "\\..\\..") from collections import namedtuple from KicadModTree import Point from KicadModTree.nodes.base import Line, Arc, Circle, Text, Pad from KicadModTree.nodes.specialized import RectFill from KicadModTree.util.kicad_util import formatFloat class Layer: _DEFAULT_LINE_WIDTHS = {'F.SilkS': 0.12, 'B.SilkS': 0.12, 'F.Fab': 0.1, 'B.Fab': 0.1, 'F.CrtYd': 0.05, 'B.CrtYd': 0.05} _DEFAULT_LINE_WIDTH = 0.15 _DEFAULT_TEXT_OFFSET = 1.0 _DEFAULT_TEXT_SIZE_MIN = 0.25 _DEFAULT_TEXT_SIZE_MAX = 2.00 _DEFAULT_GRID_CRT = 0.05 _DEFAULT_OFFSET_CRT = 0.25 _DEFAULT_SOLDERMASK_MARGIN = 0.2 # clearance? def __init__(self, footprint, layer='F.Fab', origin=(0,0), line_width=None, offset=None): self.footprint = footprint self.layer = layer self.polyline_start = None self.gridspacing = None self.keepout = None self.setOrigin(origin[0], origin[1]) self.txt_size = [1.0] * 2 self.setTextDefaults() self.setTextSize(1.0) self.txt_offset = self._DEFAULT_TEXT_OFFSET if offset == None and layer.split('.')[1] == 'CrtYd': offset = self._DEFAULT_OFFSET_CRT if offset != None: self.offset = offset self.auto_offset = offset == None self.goHome() self.setLineWidth(self._DEFAULT_LINE_WIDTHS.get(layer, self._DEFAULT_LINE_WIDTH) if line_width == None else line_width) if layer.split('.')[1] == 'CrtYd': self.setGridSpacing(self._DEFAULT_GRID_CRT) # else: # self.setGridSpacing(0.001) @staticmethod def getBevel(width, height): return min(1.0, min(width, height) * 0.25) def setOrigin(self, x, y): self.origin = (self._align(x), self._align(y)) self.goHome() return self def getOrigin(self): return self.origin def setLineWidth(self, width): self.line_width = width if self.auto_offset: self.offset = self.line_width / 2.0 return self def getSoldermaskMargin(self): return self._DEFAULT_SOLDERMASK_MARGIN def setTextDefaults(self, max_size=None, min_size=None): if max_size == None and min_size == None: self.text_size_min = self._DEFAULT_TEXT_SIZE_MIN self.text_size_max = self._DEFAULT_TEXT_SIZE_MAX else: if max_size != None: self.text_size_max = round(max_size, 2) if min_size != None: self.text_size_min = round(min_size, 2) return self def setTextSize(self, height, width=None, thickness=None): height = round(height, 2) self.txt_size[0] = min(max(height, self.text_size_min), self.text_size_max) self.txt_size[1] = min(max(height if width == None else round(width, 2), self.text_size_min), self.text_size_max) self.txt_thickness = round(self.txt_size[0] * 0.15 if thickness == None else thickness, 2) return self def setGridSpacing(self, grid): self.gridspacing = grid if self.gridspacing != None: self.alignToGrid() return self def goHome(self): self.x = self.origin[0] self.y = self.origin[1] return self def goto(self, x, y): self.x = self._align(x) self.y = self._align(y) return self def gotoX(self, x): self.x = self._align(x) return self def gotoY(self, y): self.y = self._align(y) return self def jump(self, x, y): self.x += self._align(x) self.y += self._align(y) return self def _align(self, value): return round(value, 6) if self.gridspacing == None\ else (math.ceil(value / self.gridspacing) * self.gridspacing if value > 0.0 else math.floor(value / self.gridspacing) * self.gridspacing) def alignToGrid(self): self.x = self._align(self.x) self.y = self._align(self.y) self.setOrigin(self._align(self.origin[0]), self._align(self.origin[1])) return self def _line(self, x, y): if self.keepout != None: segments = self.keepout.processLine(self.x, self.y, self.x + x, self.y + y) for line in segments: # TODO: move grid alignment to keepout code? line[0] = self._align(line[0]) line[1] = self._align(line[1]) line[2] = self._align(line[2]) line[3] = self._align(line[3]) self.footprint.append(Line(start=[line[0], line[1]], end=[line[2], line[3]], layer=self.layer, width=self.line_width)) else: self.footprint.append(Line(start=[self.x, self.y], end=[self.x + x, self.y + y], layer=self.layer, width=self.line_width)) def to(self, x, y, draw=True): x = self._align(x) y = self._align(y) if draw: self._line(x, y) self.x += x self.y += y return self def left(self, distance, draw=True): distance = self._align(distance) if draw: self._line(-distance, 0.0) self.x -= distance return self def right(self, distance, draw=True): distance = self._align(distance) if draw: self._line(distance, 0.0) self.x += distance return self def up(self, distance, draw=True): distance = self._align(distance) if draw: self._line(0.0, -distance) self.y -= distance return self def down(self, distance, draw=True): distance = self._align(distance) if draw: self._line(0.0, distance) self.y += distance return self def polyline(self, vertices, close=False): if self.polyline_start == None: self.polyline_start = (self.x, self.y) for vertex in vertices: x = self._align(vertex[0]) y = self._align(vertex[1]) self._line(self.x + x, self.y + y) self.x += x self.y += y if close: self.close() return self def close(self): if self.polyline_start != None: if self.x != self.polyline_start[0] or self.x != self.polyline_start[1]: self._line(self.polyline_start[0], self.polyline_start[1]) self.polyline_start = None return self def arc(self, center_x, center_y, angle): arc = Arc(start=[self.x, self.y], center=[self.x + center_x, self.y + center_y], angle=angle, layer=self.layer, width=self.line_width) self.footprint.append(arc) end = arc._calulateEndPos() self.x += center_x + end.y self.y += center_y + end.x return self def circle(self, radius, filled=False): if filled: line_width = radius / 3.0 + self.line_width / 2.0 r = line_width / 2.0 while r < radius: self.footprint.append(Circle(center=[self.x, self.y], radius=r, layer=self.layer, width=line_width)) r += line_width - self.line_width / 2.0 else: line_width = round(min(self.line_width, radius / 2.0), 3) self.footprint.append(Circle(center=[self.x, self.y], radius=radius, layer=self.layer, width=line_width)) return self def fillrect(self, w, h): #TODO: add origin handling x = self.x y = self.y w = self._align(w) h = self._align(h - self.line_width) #self.jump(self._align(-w / 2.0), self._align(-h / 2.0)) l = math.ceil(h / self.line_width) h = h / l self.jump(0.0, self.line_width / 2.0) while(l > 0): self._line(w, 0.0) self.jump(0.0, h) l -= 1 self.x = x self.y = y return self def rect(self, w, h, bevel=(0.0, 0.0, 0.0, 0.0), draw=(True, True, True, True), origin='center'): x = self.x y = self.y w = self._align(w) h = self._align(h) if type(bevel) in [int, float]: bevel = [bevel] * 4 elif bevel == None: bevel = [0.0] * 4 if origin == 'center': self.jump(self._align(-w / 2.0), self._align(-h / 2.0)) if bevel[0] != 0.0: self.jump(bevel[0], 0.0) self.right(w - bevel[0] - bevel[1], draw[0]) if bevel[1] != 0.0: self.to(bevel[1], bevel[1]) self.down(h - bevel[1] - bevel[2], draw[1]) if bevel[2] != 0.0: self.to(-bevel[2], bevel[2]) self.left(w - bevel[3] - bevel[2], draw[2]) if bevel[3] != 0.0: self.to(-bevel[3], -bevel[3]) self.up(h - bevel[3] - bevel[0], draw[3]) if bevel[0] != 0.0: self.to(bevel[0], -bevel[0]) self.x = x self.y = y return self def rrect(self, w, h, radius, origin='center'): x = self.x y = self.y w = self._align(w) h = self._align(h) if origin == 'center': self.jump(self._align(-w / 2.0), self._align(-h / 2.0)) w -= radius * 2.0 h -= radius * 2.0 self.jump(radius, 0.0) self.right(w) self.arc(0.0, radius, 90.0) self.down(h) self.arc(-radius, 0.0, 90.0) self.left(w) self.arc(0.0, -radius, 90.0) self.up(h) self.arc(radius, 0.0, 90.0) self.x = x self.y = y return self def text(self, type, text, rotation=0): self.footprint.append(Text(type=type, text=text, at=[self.x, self.y], rotation=rotation, layer=self.layer, size=self.txt_size, thickness=self.txt_thickness)) return self # TODO: add methods for offsetting etc class PolyLine (): def __init__(self, vertices=None): self.vertices = [] if vertices != None: for vertex in vertices: self.vertices.append(Point(vertex)) def __getattr__(self, name): if name == "isClosed": return False if len(self.vertices) < 3 else self.vertices[0].x == self.vertices[-1].x and self.vertices[0].y == self.vertices[-1].y else: raise AttributeError def append(self, x, y): self.vertices.append([x, y]) return self class PadLayer: def __init__(self, footprint, size, type, shape, shape_first=None, drill=None, layers=None, x_offset=0.0, y_offset=0.0): self.footprint = footprint self.type = type self.layers = layers self.shape = shape self.shape_first = shape if shape_first == None else shape_first self.size = size self.drill = 0.5 if drill == None and type == Pad.TYPE_SMT else drill self.x_offset = x_offset self.y_offset = y_offset self._init_layers(layers) self.p = 1 self.last_pad = None def _init_layers(self, layers): if layers == None: if self.type == Pad.TYPE_SMT: layers = Pad.LAYERS_SMT elif self.type == Pad.TYPE_THT: layers = Pad.LAYERS_THT self.layers=layers def add(self, x, y, number=None, type=None, shape=None, size=None, x_offset=None, y_offset=None): if number == None: number = self.p self.p += 1 if x_offset == None: x_offset = self.x_offset if y_offset == None: y_offset = self.y_offset if shape == None: shape=self.shape_first if number == 1 else self.shape self.last_pad = Pad(number=number, type=self.type if type == None else type, shape=shape, at=[x + x_offset, y + y_offset], size=self.size if size == None else size, drill=self.drill, layers=self.layers) self.footprint.append(self.last_pad) return self def getLast(self): return self.last_pad _RectWH = namedtuple("_RectWH", [ 'x', 'y', 'height', 'width' ]) class _Point: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return "(x={x}, y={y})".format(x=formatFloat(self.x), y=formatFloat(self.y)) class _Line: def __init__(self, a, b, x1=None, y1=None, normalize=False): if x1 == None and y1 == None: self._add_points(a, b, normalize) else: self._add_points(_Point(a, b), _Point(x1, y1), normalize) def _add_points(self, a, b, normalize): if normalize: self.x0 = round(min(a.x, b.x), 8) self.x1 = round(max(a.x, b.x), 8) self.y0 = round(min(a.y, b.y), 8) self.y1 = round(max(a.y, b.y), 8) elif a.y < b.y: self.x0 = a.x self.x1 = b.x self.y0 = a.y self.y1 = b.y else: self.x0 = b.x self.x1 = a.x self.y0 = b.y self.y1 = a.y def __repr__(self): return "(x0={x0}, y0={y0}, x1={x1}, y1={y1})".format(x0=formatFloat(self.x0), y0=formatFloat(self.y0), x1=formatFloat(self.x1), y1=formatFloat(self.y1)) class _Keepout: def __init__(self, a, b, x1=None, y1=None, radius=0.0): self.lines = [] self.radius = radius if x1 == None and y1 == None: self._add_points(a, b) else: self._add_points(_Point(a, b), _Point(x1, y1)) def _add_points(self, a, b): self.x0 = round(min(a.x, b.x), 5) self.x1 = round(max(a.x, b.x), 5) self.y0 = round(min(a.y, b.y), 5) self.y1 = round(max(a.y, b.y), 5) def pointIsInside(self, x, y): x = round(x, 5); y = round(y, 5) return x >= self.x0 and x <= self.x1 and y >= self.y0 and y <= self.y1 def _feq(self, a, b): return abs(a-b) < 0.0001 def _bbox_overlap(self, bbox): x0 = min(bbox.x0, bbox.x1) x1 = max(bbox.x0, bbox.x1) y0 = min(bbox.y0, bbox.y1) y1 = max(bbox.y0, bbox.y1) return not (self.x0 < x1 and self.x1 > x0 and self.y0 > y1 and self.y1 < y0) def lineIntersects(self, l): # skip proccesing if line bounding box is completely outside keepout bounding box if not self._bbox_overlap(l): return False points = [] # get lines representing keepout bounding box if len(self.lines) == 0: self.lines.append(_Line(self.x0, self.y0, self.x1, self.y0)) self.lines.append(_Line(self.x1, self.y0, self.x1, self.y1)) self.lines.append(_Line(self.x0, self.y1, self.x1, self.y1)) self.lines.append(_Line(self.x0, self.y0, self.x0, self.y1)) # find and return intersecting points a1 = l.y1 - l.y0 b1 = l.x0 - l.x1 lr = l.x1 > l.x0 i = 0 for k in self.lines: a2 = k.y1 - k.y0 b2 = k.x0 - k.x1 d = a1 * b2 - a2 * b1 if d != 0.0: c2 = a2 * k.x0 + b2 * k.y0; c1 = a1 * l.x0 + b1 * l.y0 xp = (b2 * c1 - b1 * c2) / d yp = (a1 * c2 - a2 * c1) / d ka = (xp >= l.x0 and xp <= l.x1) if lr else (xp <= l.x0 and xp >= l.x1) kb = self._feq(xp, k.x0) if k.x0 == k.x1 else self._feq(yp, k.y0) if ka and kb and self.pointIsInside(xp, yp): if lr and (i == 0 or i == 3): points.insert(0, [xp, yp, i]) else: points.append([xp, yp, i]) i += 1 return False if len(points) == 0 else points def HlineIntersects(self, y): return y > self.y0 and y < self.y1 def VlineIntersects(self, x): return round(x, 8) > self.x0 and round(x, 8) < self.x1 def _HLineTrim(self, y, r): h = (self.y0 + r - y if y < self.y0 + r else y - self.y1 + r) return r - math.sqrt(r * r - h * h) def _VLineTrim(self, x, r): h = (self.x0 + r - x if x < self.x0 + r else x - self.x1 + r) return r - math.sqrt(r * r - h * h) def HLineTrim(self, l): line = _Line(l[0], l[1], l[2], l[3], normalize=True) # check if line is outside rectangular bounding box and exit if so if line.x1 < self.x0 or line.x0 > self.x1: return False # check if line completely inside rectangular bounding box and exit with no segments if so if self.radius == 0.0 and line.x0 >= self.x0 and line.x1 <= self.x1: return [] r = self.radius segments = [] if r == 0.0 or (line.y0 >= self.y0 + r and line.y0 <= self.y1 - r): if line.x0 < self.x0: segments.append([line.x0, line.y0, self.x0, line.y1]) if line.x1 > self.x1: segments.append([self.x1, line.y0, line.x1, line.y1]) elif line.x1 > self.x0 and line.x0 < self.x1: h = self._HLineTrim(line.y0, r) if line.x0 < self.x0 + r: segments.append([line.x0, line.y0, min(line.x1, self.x0 + h), line.y1]) if line.x1 > self.x1 - r: segments.append([max(line.x0, self.x1 - h), line.y0, line.x1, line.y1]) return False if len(segments) == 0 else segments def VLineTrim(self, l): line = _Line(l[0], l[1], l[2], l[3], normalize=True) # check if line is outside if line.y1 <= self.y0 or line.y0 >= self.y1: return False # check if line completely inside rectangular bounding box and exit with no segments if so if self.radius == 0.0 and line.y0 >= self.y0 and line.y1 <= self.y1: return [] r = self.radius segments = [] if r == 0.0 or (line.x0 >= self.x0 + r and line.x0 <= self.x1 - r): if line.y0 < self.y0: segments.append([line.x0, line.y0, line.x1, self.y0]) if line.y1 > self.y1: segments.append([line.x0, self.y1, line.x1, line.y1]) elif line.y1 > self.y0 and line.y0 < self.y1: h = self._VLineTrim(line.x0, r) if line.y0 < self.y0 + r: segments.append([line.x0, line.y0, line.x1, min(line.y1, self.y0 + h)]) if line.y1 > self.y1 - r: segments.append([line.x0, max(self.y1 - h, line.y0), line.x1, line.y1]) return False if len(segments) == 0 else segments def __repr__(self): return "(x0={x0}, y0={y0}, x1={x1}, y1={y1}, r={r})".format(x0=formatFloat(self.x0), y0=formatFloat(self.y0), x1=formatFloat(self.x1), y1=formatFloat(self.y1), r=formatFloat(self.radius)) class Keepout(): DEBUG = 0 _NUM_RECTS = 5 def __init__(self, layer): self.layer = layer self.keepouts = [] self.min_length = 0.01 layer.keepout = self # float-variant of range() @staticmethod def frange(x, y, jump): while x < y: yield x x += jump def __getattr__(self, name): if name == "offset": return self.layer.line_width / 2.0 + self.layer.getSoldermaskMargin() else: raise AttributeError def _align(self, value): return self.layer._align(value) def _add(self, x0, y0, x1, y1, radius=0.0): self.keepouts.append(_Keepout(self._align(x0), self._align(y0), self._align(x1), self._align(y1), radius)) # add keepout area for rectangle def addRect(self, x, y, w, h, offset=None): if offset == None: offset = 0.0 w = w / 2.0 + offset h = h / 2.0 + offset self._add(x - w, y - h, x + w, y + h) return self # add keepout area for circular or oval object def addRound(self, x, y, w, h, offset=None): if offset == None: offset = self.offset # d = w - h r = min(h, w) / 2.0 + offset w = w / 2.0 + offset h = h / 2.0 + offset self._add(x - w, y - h, x + w, y + h, r) # self.addRect(x - w, y - w, d if d > 0.0 else 0.0, -d if d < 0.0 else 0.0, r) return self def addPads(self): nodes = self.layer.footprint.getNormalChilds() offset = self.offset for node in nodes: if isinstance(node, Pad): if node.shape == Pad.SHAPE_RECT: self.addRect(node.at.x, node.at.y, node.size.x, node.size.y, offset) else: self.addRound(node.at.x, node.at.y, node.size.x, node.size.y, offset) def getPadBB(self, number): # TODO: use node.calculateBoundingBox when implemented, this is a simple version that does not honor any rotation nodes = self.layer.footprint.getNormalChilds() offset = self.offset * 2.0 bb = None for node in nodes: if isinstance(node, Pad) and node.number == number: bb = _RectWH(x = node.at.x, y = node.at.y, width = node.size.x + offset, height = node.size.y + offset) return bb # internal method for keepout-processing def _processHVLine(self, line): def add_segment(x0, y0, x1, y1): length = x1 - x0 + y1 - y0 if length >= self.min_length: segments.append([x0, y0, x1, y1]) vertical = line.x0 == line.x1 segments = [[line.x0, line.y0, line.x1, line.y1]] if self.DEBUG & 2: print("S", line) changes = len(self.keepouts) > 0 while changes != False: changes = False for keepout in self.keepouts: if keepout.VlineIntersects(line.x0) if vertical else keepout.HlineIntersects(line.y0): for i in reversed(range(0, len(segments))): segment = segments[i] changes = keepout.VLineTrim(segment) if vertical else keepout.HLineTrim(segment) if changes != False: segments.pop(i) for segment in changes: add_segment(segment[0], segment[1], segment[2], segment[3]) if self.DEBUG & 2: print("CHOP - line:", segment[0], segment[1], segment[2], segment[3], "keepout:", keepout) if changes != False: break if self.DEBUG & 2: print("LI", segments) return segments # split an arbitrary line so it does not interfere with keepout areas defined as [[x0,x1,y0,y1], ...] def processLine(self, x0, y0, x1, y1): line = _Line(x0, y0, x1, y1, normalize=True) if line.x0 == line.x1 or line.y0 == line.y1: # use simpler and faster algorithm for horizontal and vertical lines return self._processHVLine(line) # TODO: update to handle keepout area proper, now only respects the bounding box. segments=[[line.x0, line.y0, line.x1, line.y1]] for keepout in self.keepouts: for i in reversed(range(0, len(segments))): segment = segments[i] changes = keepout.lineIntersects(_Line(segment[0], segment[1], segment[2], segment[3])) if changes != False: segments.pop(i) segments.append([segment[0], segment[1], changes[0][0], changes[0][1]]) if len(changes) == 2: segments.append([changes[1][0], changes[1][1], segment[2], segment[3]]) return segments # draws the keepouts def debug_draw(self): if self.DEBUG & 1: x = self.layer.x y = self.layer.y lw = self.layer.line_width self.layer.line_width = 0.01 self.layer.keepout = None for keepout in self.keepouts: self.layer.goto(keepout.x0, keepout.y0) if(keepout.radius > 0.0): self.layer.rrect(keepout.x1 - keepout.x0, keepout.y1 - keepout.y0, keepout.radius, origin="topLeft") self.layer.rect(keepout.x1 - keepout.x0, keepout.y1 - keepout.y0, origin="topLeft") self.layer.line_width = lw self.layer.keepout = self self.layer.x = x self.layer.y = y class OutDir: def __init__(self, root_dir=None): self.root_dir = "" if root_dir == None else root_dir if root_dir != "" and self.root_dir[-1] != os.sep: self.root_dir += os.sep def saveTo(self, lib_name): out_dir = "" if self.root_dir == "" else self.root_dir + lib_name + ".pretty" + os.sep if not os.path.exists(out_dir): os.makedirs(out_dir) return out_dir ### EOF ### ================================================ FILE: scripts/Connector_PinSocket/cq_base_parameters.py ================================================ # -*- coding: utf8 -*- #!/usr/bin/python # # # Parts script module for socket strip footprints for KicCad # # This module is built on top of the kicad-footprint-generator framework # by Thomas Pointhuber, https://github.com/pointhi/kicad-footprint-generator # # This module 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. # # This module 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2017 Terje Io, # # 2017-11-25 # # parts of this code is based on work by other contributors # from collections import namedtuple ### use enums (Phyton 3+) class CaseType: r"""A class for holding constants for part types .. note:: will be changed to enum when Python version allows it """ THT = 'THT' r"""THT - trough hole part """ SMD = 'SMD' r"""SMD - surface mounted part """ class PinStyle: r"""A class for holding constants for pin styles .. note:: will be changed to enum when Python version allows it """ STRAIGHT = 'Straight' ANGLED = 'Angled' ### # # The following classes must be subclassed # class PartParametersBase: """ .. document private functions .. automethod:: _make_params """ Model = namedtuple("Model", [ 'variant', # generic model name 'params', # parameters 'model' # model creator class ]) """ Internally used for passing information from the base parameters to the class instance used for creating models .. py:attribute:: variant The generic name from the list of parameters .. py:attribute:: params The final parameters passed to the class instance .. py:attribute:: model The class instance itself """ Params = namedtuple("Params", [ 'num_pins', 'pin_pitch', 'pin_style', 'type' ]) """ Basic parameters for parts, if further parameters are required this should be subclassed/overriden .. note:: The existing parameters should be kept with the same name when overriden as the framework requires them .. py:attribute:: num_pins Number of pins, for parts with this is usually set to None for .. py:attribute:: pin_pitch The final parameters passed to the class instance .. py:attribute:: pin_style The class instance itself .. py:attribute:: type The class instance itself """ def __init__(self): self.base_params = {} def _make_params(self, pin_pitch, num_pin_rows, pin_style, type): r"""add a list of new points """ return self.Params( num_pins = None, # to be added programmatically pin_pitch = pin_pitch, # pin pitch pin_style = pin_style, # pin style: 'Straight' or 'Angled' type = type # part type: 'THT' or 'SMD' ) def getAllModels(self, model_classes): r"""Generate model parameters for all series and variants Loops through all base parameters and model classes instantiating the classes and checks whether a variant should be made. If a variant is to be made a namedtuple is made with the index from a call to the model instance makeModelName method and the base parameters are copied to this. When copying the base parameters others may be added such as number of pins (num_pins). .. note:: Typically this method is overriden in order to add calculated parameters like number of pins. The model specific parameters are contained in the model class itself. :param model_classes: list of part creator classes inherited from :class:`cq_base_model.PartBase` :type model_classes: ``list of classes`` :rtype: ```tuple```` """ models = {} # instantiate generator classes in order to make a dictionary of all model names for i in range(0, len(model_classes)): for variant in self.base_params.keys(): params = self.base_params[variant] model = model_classes[i](params) if model.make_me: models[model.makeModelName(variant)] = self.Model(variant, params, model_classes[i]) return models def getSampleModels(self, model_classes): r"""Generate model parameters for all series and variants Loops through all base parameters and model classes instantiating the classes and checks whether a variant should be made. If a variant is to be made a namedtuple is made with the index from a call to the model instance makeModelName method and the base parameters are copied to this. When copying the base parameters others may be added such as number of pins (num_pins). .. note:: Typically this method is overriden in order to add calculated parameters like number of pins. The model specific parameters are contained in the model class itself. :param model_classes: list of part creator classes inherited from :class:`cq_base_model.PartBase` :type model_classes: ``list of classes`` :rtype: ```tuple```` """ models = {} # instantiate generator classes in order to make a dictionary of all model names for i in range(0, len(model_classes)): for variant in self.base_params.keys(): params = self.base_params[variant] model = model_classes[i](params) if model.make_me: models[model.makeModelName(variant)] = self.Model(variant, params, model_classes[i]) return models ================================================ FILE: scripts/Connector_PinSocket/main_generator.py ================================================ # -*- coding: utf8 -*- #!/usr/bin/env python # # Parts script module for socket strip footprints for KicCad # # This module is built on top of the kicad-footprint-generator framework # by Thomas Pointhuber, https://github.com/pointhi/kicad-footprint-generator # # This module 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. # # This module 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2017 Terje Io, # # 2017-11-25 # # NOTE: many footprints are based on legacy dimensions which does not have any documented datasheet sources # see parameter.yaml for which # import sys from parameters import params import socket_strips if __name__ == '__main__': series = [ socket_strips.pinSocketVerticalTHT, socket_strips.pinSocketHorizontalTHT, socket_strips.pinSocketVerticalSMD ] params = params() if params.loaded is not True: print(params.loaded) sys.exit(1) # models = params.getSampleModels(series, 4) models = params.getAllModels(series) i = 0 for variant in models.keys(): params = models[variant].params model = models[variant].model(params) if model.make_me: model.make() i += 1 print("\nFootprints made:", i) ### EOF ### ================================================ FILE: scripts/Connector_PinSocket/parameters.py ================================================ # -*- coding: utf8 -*- #!/usr/bin/python # #**************************************************************************** #* * #* class for generating and importing parameters for pin sockets parts * #* * #* This is part of FreeCAD & cadquery tools * #* to export generated models in STEP & VRML format. * #* Copyright (c) 2017 * #* Terje Io https://github.com/terjeio * #* * #* All trademarks within this guide belong to their legitimate owners. * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * #* as published by the Free Software Foundation; either version 2 of * #* the License, or (at your option) any later version. * #* for detail see the LICENCE text file. * #* * #* This program 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 Library General Public License for more details. * #* * #* You should have received a copy of the GNU Library General Public * #* License along with this program; if not, write to the Free Software * #* Foundation, Inc., * #* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * #* * #**************************************************************************** import os import yaml from collections import namedtuple from cq_base_parameters import PartParametersBase, PinStyle, CaseType class params (PartParametersBase): Params = namedtuple("Params", [ 'num_pins', 'num_pin_rows', 'pin_pitch', 'pin_style', 'type', 'pin1start_right' ]) DParams = namedtuple("DParams", [ 'type', 'num_pins', 'num_pin_rows', 'pin_pitch', 'pin_style', 'pin_length', 'pin_width', 'pin_thickness', 'pin_drill', 'pins_min', 'pins_max', 'pin1start_right', 'pad_width', 'pad_length', 'pads_lp_width', 'pins_offset', 'body_width', 'body_height', 'body_length', 'body_overlength', 'body_offset', 'datasheet', ]) def __init__(self, parameter_file=None): self.devices = {} self.base_params = { # # E - pin rows distance # P - total number of pins # Case - case type # Generic name E P Case #"THT-1x1.27mm_Horizontal" : self._make_params(1.27, 1, PinStyle.ANGLED, CaseType.THT, True), "THT-1x2.00mm_Horizontal" : self._make_params(2.00, 1, PinStyle.ANGLED, CaseType.THT, True), "THT-1x2.54mm_Horizontal" : self._make_params(2.54, 1, PinStyle.ANGLED, CaseType.THT, True), "THT-1x1.00mm_Vertical" : self._make_params(1.00, 1, PinStyle.STRAIGHT, CaseType.THT, True), "THT-1x1.27mm_Vertical" : self._make_params(1.27, 1, PinStyle.STRAIGHT, CaseType.THT, True), "THT-1x2.00mm_Vertical" : self._make_params(2.00, 1, PinStyle.STRAIGHT, CaseType.THT, True), "THT-1x2.54mm_Vertical" : self._make_params(2.54, 1, PinStyle.STRAIGHT, CaseType.THT, True), "THT-2x1.27mm_Horizontal" : self._make_params(1.27, 2, PinStyle.ANGLED, CaseType.THT, True), "THT-2x2.00mm_Horizontal" : self._make_params(2.00, 2, PinStyle.ANGLED, CaseType.THT, True), "THT-2x2.54mm_Horizontal" : self._make_params(2.54, 2, PinStyle.ANGLED, CaseType.THT, True), "THT-2x1.27mm_Vertical" : self._make_params(1.27, 2, PinStyle.STRAIGHT, CaseType.THT, True), "THT-2x2.00mm_Vertical" : self._make_params(2.00, 2, PinStyle.STRAIGHT, CaseType.THT, True), "THT-2x2.54mm_Vertical" : self._make_params(2.54, 2, PinStyle.STRAIGHT, CaseType.THT, True), "SMD-1x1.00mm_Vertical_Right" : self._make_params(1.00, 1, PinStyle.STRAIGHT, CaseType.SMD, True), "SMD-1x1.27mm_Vertical_Right" : self._make_params(1.27, 1, PinStyle.STRAIGHT, CaseType.SMD, True), "SMD-1x2.00mm_Vertical_Right" : self._make_params(2.00, 1, PinStyle.STRAIGHT, CaseType.SMD, True), "SMD-1x2.54mm_Vertical_Right" : self._make_params(2.54, 1, PinStyle.STRAIGHT, CaseType.SMD, True), "SMD-1x1.00mm_Vertical_Left" : self._make_params(1.00, 1, PinStyle.STRAIGHT, CaseType.SMD, False), "SMD-1x1.27mm_Vertical_Left" : self._make_params(1.27, 1, PinStyle.STRAIGHT, CaseType.SMD, False), "SMD-1x2.00mm_Vertical_Left" : self._make_params(2.00, 1, PinStyle.STRAIGHT, CaseType.SMD, False), "SMD-1x2.54mm_Vertical_Left" : self._make_params(2.54, 1, PinStyle.STRAIGHT, CaseType.SMD, False), "SMD-2x1.00mm_Vertical" : self._make_params(1.00, 2, PinStyle.STRAIGHT, CaseType.SMD, True), "SMD-2x1.27mm_Vertical" : self._make_params(1.27, 2, PinStyle.STRAIGHT, CaseType.SMD, True), "SMD-2x2.00mm_Vertical" : self._make_params(2.00, 2, PinStyle.STRAIGHT, CaseType.SMD, True), "SMD-2x2.54mm_Vertical" : self._make_params(2.54, 2, PinStyle.STRAIGHT, CaseType.SMD, True) } if parameter_file == None: parameter_file = os.path.dirname(os.path.realpath(__file__)) + os.sep + "parameters.yaml" try: devices = yaml.safe_load_all(open(parameter_file)) for device in devices: params = self._import_params(device) if not params == False: self.devices[device['series']] = params self.loaded = True except Exception as exception: self.loaded = 'Failed to load parameters: {e}'.format(e=exception) return def _import_params(self, device): if device['series'] in self.base_params: base = self.base_params[device['series']] return self.DParams( num_pins = None, # to be added programmatically type = base.type, num_pin_rows = base.num_pin_rows, pin_pitch = base.pin_pitch, pin_style = base.pin_style, pin1start_right = base.pin1start_right, pin_length = device['pins']['length'], pin_width = device['pins']['width'], pin_thickness = device['pins']['thickness'], pins_offset = device['pins']['offset'], pin_drill = device['pins']['drill'], pins_min = int(device['pins']['min']), pins_max = int(device['pins']['max']), body_width = device['body']['width'], body_height = device['body']['height'], body_length = None, # will be calculated by the render class body_overlength = device['body']['overlength'], body_offset = device['body']['offset'], pad_width = device['pads']['width'], pad_length = device['pads']['length'], pads_lp_width = device['pads']['lp_width'], datasheet = device['datasheet'], ) else: return False def _make_params(self, pin_pitch, num_pin_rows, pin_style, type, pin1start_right): return self.Params( num_pins = None, # to be added programmatically num_pin_rows = num_pin_rows, # number of pin rows pin_pitch = pin_pitch, # pin pitch pin_style = pin_style, # pin style: 'Straight' or 'Angled' type = type, # part type: 'THT' or 'SMD' pin1start_right = pin1start_right # True if pin 1 start at right ) def getAllModels(self, model_classes): models = {} # instantiate generator classes in order to make a dictionary of all variants for i in range(0, len(model_classes)): for variant in self.devices.keys(): for pin_columns in range(self.devices[variant].pins_min, self.devices[variant].pins_max + 1): params = self.devices[variant]._replace(num_pins = pin_columns) model = model_classes[i](params) if model.make_me: models[model.makeModelName(variant)] = self.Model(variant, params, model_classes[i]) return models def getSampleModels(self, model_classes): models = {} # instantiate generator classes in order to make a dictionary of all default variants for i in range(0, len(model_classes)): for variant in self.devices.keys(): params = self.devices[variant]._replace(num_pins = 5 * self.devices[variant].num_pin_rows) model = model_classes[i](params) if model.make_me: models[model.makeModelName(variant)] = self.Model(variant, params, model_classes[i]) return models def getModel(self, model_class, variant): model = variant in self.devices # instantiate generator class in order to make a dictionary entry for a single variant if model: params = self.devices[variant]._replace(num_pins = 5 * self.devices[variant].num_pin_rows) model = model_class(params) if not model.make_me: model = False return model ### EOF ### ================================================ FILE: scripts/Connector_PinSocket/parameters.yaml ================================================ # # Pin Sockets - footprint and 3D dimensions # NOTE for SMD parts: pins.length is overall length (tip to tip) # pads.lp_width is overall land pattern width # 2017-11-25 # series: THT-1x1.00mm_Vertical body: width: 1.5 height: 2.1 overlength: 0.5 offset: 0.0 pins: min: 2 max: 40 width: 0.3 thickness: 0.1 drill: 0.5 length: 1.8 offset: 0.29 pads: length: 0.85 width: 0.85 lp_width: 0 datasheet: https://gct.co/files/drawings/bc065.pdf --- series: THT-1x1.27mm_Vertical body: width: 2.54 height: 4.4 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.5 thickness: 0.2 drill: 0.7 length: 2.4 offset: 0.0 pads: length: 1.0 width: 1.0 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-1x2.00mm_Vertical body: width: 2.0 height: 5.6 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 0.8 length: 2.5 offset: 0.0 pads: length: 1.35 width: 1.35 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-1x2.54mm_Vertical body: width: 2.54 height: 7.0 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 1.0 length: 2.9 offset: 0.0 pads: length: 1.7 width: 1.7 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-2x1.00mm_Vertical N/A body: width: 1.5 height: 2.1 overlength: 0.75 offset: 0.0 pins: min: 1 max: 40 width: 0.3 thickness: 0.1 drill: 0.5 length: 1.8 offset: 0.29 pads: length: 0 width: 0 lp_width: 0 datasheet: --- series: THT-2x1.27mm_Vertical body: width: 3.05 height: 4.4 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.5 thickness: 0.2 drill: 0.7 length: 2.4 offset: 0.0 pads: length: 1.0 width: 1.0 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-2x2.00mm_Vertical body: width: 4.0 height: 5.6 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 0.8 length: 2.5 offset: 0.0 pads: length: 1.35 width: 1.35 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-2x2.54mm_Vertical body: width: 5.08 height: 7.0 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 1.0 length: 2.9 offset: 0.0 pads: length: 1.7 width: 1.7 lp_width: 0 datasheet: from Kicad 4.0.7 --- # # Horizontal THT parts # series: THT-1x1.00mm_Horizontal N/A body: width: 1.5 height: 2.1 overlength: 0.75 offset: 0.0 pins: min: 1 max: 40 width: 0.3 thickness: 0.1 drill: 0.5 length: 1.8 offset: 0.29 pads: length: 0 width: 0 lp_width: 0 datasheet: --- series: THT-1x1.27mm_Horizontal body: width: 4.3 height: 1.8 overlength: 0.35 offset: 0.15 pins: min: 3 max: 40 width: 0.42 thickness: 0.15 drill: 0.65 length: 2.0 offset: 0.0 pads: length: 1.0 width: 1.0 lp_width: 0 datasheet: https://gct.co/pdfjs/web/viewer.html?file=/Files/Drawings/BD090.pdf&t=1511593690632 --- series: THT-1x2.00mm_Horizontal body: width: 6.35 height: 2.0 overlength: 0.0 offset: 1.27 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 0.8 length: 2.5 offset: 0.2 pads: length: 1.35 width: 1.35 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-1x2.54mm_Horizontal body: width: 8.51 height: 2.54 overlength: 0.0 offset: 1.52 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 1.0 length: 2.9 offset: 0.2 pads: length: 1.7 width: 1.7 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-2x1.00mm_Horizontal N/A body: width: 1.5 height: 2.1 overlength: 0.75 offset: 0.0 pins: min: 1 max: 40 width: 0.3 thickness: 0.1 drill: 0.5 length: 1.8 offset: 0.29 pads: length: 0 width: 0 lp_width: 0 datasheet: --- series: THT-2x1.27mm_Horizontal body: width: 4.4 height: 3.10 overlength: 0.35 offset: 0.15 pins: min: 3 max: 50 width: 0.5 thickness: 0.15 drill: 0.65 length: 2.0 offset: 0.15 pads: length: 1.0 width: 1.0 lp_width: 0 datasheet: https://gct.co/pdfjs/web/viewer.html?file=/Files/Drawings/BD091.pdf&t=1511594177220 --- series: THT-2x2.00mm_Horizontal body: width: 6.35 height: 4.0 overlength: 0.0 offset: 1.27 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 0.8 length: 2.5 offset: 0.2 pads: length: 1.35 width: 1.35 lp_width: 0 datasheet: from Kicad 4.0.7 --- series: THT-2x2.54mm_Horizontal body: width: 8.51 height: 5.08 overlength: 0.0 offset: 1.52 pins: min: 1 max: 40 width: 0.6 thickness: 0.2 drill: 1.0 length: 2.5 offset: 0.2 pads: length: 1.7 width: 1.7 lp_width: 0 datasheet: from Kicad 4.0.7 --- # # SMD parts # series: SMD-1x1.00mm_Vertical_Right body: width: 1.5 height: 2.25 overlength: 0.5 offset: 0.0 pins: min: 2 max: 40 width: 0.3 thickness: 0.1 drill: None length: 2.9 offset: 0.0 pads: length: 1.95 width: 0.50 lp_width: 3.9 datasheet: https://gct.co/files/drawings/bc070.pdf --- series: SMD-1x1.00mm_Vertical_Left body: width: 1.5 height: 2.25 overlength: 0.5 offset: 0.0 pins: min: 2 max: 40 width: 0.3 thickness: 0.1 drill: None length: 2.9 offset: 0.0 pads: length: 1.95 width: 0.50 lp_width: 3.9 datasheet: https://gct.co/files/drawings/bc070.pdf --- series: SMD-1x1.27mm_Vertical_Right body: width: 1.8 height: 4.6 overlength: 0.35 offset: 0.0 pins: min: 2 max: 40 width: 0.42 thickness: 0.15 drill: None length: 3.5 offset: 0.0 pads: length: 1.8 width: 0.65 lp_width: 4.5 datasheet: https://gct.co/pdfjs/web/viewer.html?file=/Files/Drawings/BD075.pdf&t=1511594726925 --- series: SMD-1x1.27mm_Vertical_Left body: width: 1.8 height: 4.6 overlength: 0.35 offset: 0.0 pins: min: 2 max: 40 width: 0.42 thickness: 0.15 drill: None length: 3.5 offset: 0.0 pads: length: 1.8 width: 0.65 lp_width: 4.5 datasheet: https://gct.co/pdfjs/web/viewer.html?file=/Files/Drawings/BD075.pdf&t=1511594726925 --- series: SMD-1x2.00mm_Vertical_Right body: width: 2.5 height: 4.3 overlength: 0.6 offset: 0.0 pins: min: 2 max: 40 width: 0.5 thickness: 0.2 drill: None length: 4.2 offset: 0.0 pads: length: 2.0 width: 0.9 lp_width: 5.2 datasheet: https://www.jayconsystems.com/fileuploader/download/download/?d=1&file=custom%2Fupload%2FFile-1375728122.pdf --- series: SMD-1x2.00mm_Vertical_Left body: width: 2.5 height: 4.3 overlength: 0.6 offset: 0.0 pins: min: 2 max: 40 width: 0.5 thickness: 0.2 drill: None length: 4.2 offset: 0.0 pads: length: 2.0 width: 0.9 lp_width: 5.2 datasheet: https://www.jayconsystems.com/fileuploader/download/download/?d=1&file=custom%2Fupload%2FFile-1375728122.pdf --- series: SMD-1x2.54mm_Vertical_Right body: width: 2.54 height: 7.1 overlength: 0.2 offset: 0.0 pins: min: 2 max: 40 width: 0.6 thickness: 0.2 drill: None length: 4.54 offset: 0.0 pads: length: 1.9 width: 1.0 lp_width: 5.2 datasheet: https://cdn.harwin.com/pdfs/M20-786.pdf --- series: SMD-1x2.54mm_Vertical_Left body: width: 2.54 height: 7.1 overlength: 0.2 offset: 0.0 pins: min: 2 max: 40 width: 0.6 thickness: 0.2 drill: None length: 4.54 offset: 0.0 pads: length: 1.9 width: 1.0 lp_width: 5.2 datasheet: https://cdn.harwin.com/pdfs/M20-786.pdf --- series: SMD-2x1.00mm_Vertical body: width: 2.5 height: 2.25 overlength: 0.5 offset: 0.0 pins: min: 2 max: 40 width: 0.3 thickness: 0.1 drill: None length: 3.9 offset: 0.0 pads: length: 1.85 width: 0.50 lp_width: 4.9 datasheet: https://gct.co/files/drawings/bc085.pdf --- series: SMD-2x1.27mm_Vertical body: width: 2.54 height: 4.6 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.4 thickness: 0.15 drill: None length: 5.11 offset: 0.0 pads: length: 2.1 width: 0.75 lp_width: 5.7 datasheet: from Kicad 4.0.7! --- series: SMD-2x2.00mm_Vertical body: width: 4.0 height: 4.5 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.5 thickness: 0.2 drill: None length: 6.0 offset: 0.0 pads: length: 2.75 width: 1.0 lp_width: 9.0 datasheet: from Kicad 4.0.7 --- series: SMD-2x2.54mm_Vertical body: width: 5.08 height: 7.0 overlength: 0.0 offset: 0.0 pins: min: 1 max: 40 width: 0.64 thickness: 0.2 drill: None length: 7.84 offset: 0.0 pads: length: 3.0 width: 1.0 lp_width: 8.04 datasheet: from Kicad 4.0.7 ================================================ FILE: scripts/Connector_PinSocket/socket_strips.py ================================================ #!/usr/bin/env python # # Parts script module for socket strip footprints for KicCad # # This script is built on top of the kicad-footprint-generator framework # by Thomas Pointhuber, https://github.com/pointhi/kicad-footprint-generator # # This module 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. # # This module 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # based on scripts/tools/footprint_scripts_pin_headers.py # refactored by and (C) 2017 Terje Io, # # 2017-11-25 import sys import os sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../..") from KicadModTree import Footprint, Translation, Pad, Model, KicadFileHandler from canvas import Layer, PadLayer, Keepout, OutDir from cq_base_parameters import PinStyle, CaseType txt_descr = ["", ", single row", ", double cols", ", double cols", ", triple cols", ", quadruple cols"] txt_tag = ["", " single row", " double row", ", triple cols", " quadruple row"] root_dir = OutDir("./") #Keepout.DEBUG = 1 def getPadOffsets(overall_width, pad): return round((overall_width - pad[0]) / 2.0, 3) def getPinLength(overall_width, packwidth): return round((overall_width - packwidth) / 2.0, 3) class pinSocketVerticalTHT (object): def __init__(self, params): self.make_me = params.type == CaseType.THT and params.pin_style == PinStyle.STRAIGHT and params.pad_width > 0 self.params = params def makeModelName(self, genericName): return "PinSocket_{0}x{1:02}_P{2:03.2f}mm_Vertical".format(self.params.num_pin_rows, self.params.num_pins, self.params.pin_pitch) def make(self, tags_additional=[], isSocket=True): param = self.params lib_name ="Connector_PinSocket_{0:03.2f}mm".format(param.pin_pitch) footprint_name = self.makeModelName("") description = "Through hole straight socket strip, {0}x{1:02}, {2:03.2f}mm pitch".format(param.num_pin_rows, param.num_pins, param.pin_pitch) tags = "Through hole socket strip THT {0}x{1:02} {2:03.2f}mm".format(param.num_pin_rows, param.num_pins, param.pin_pitch) tags += txt_tag[param.num_pin_rows] description += txt_descr[param.num_pin_rows] pad = [param.pad_length, param.pad_width] rowdist = param.pin_pitch if len(tags_additional) > 0: for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t if len(param.datasheet) > 0: description += " (" + param.datasheet + ")" description += ", script generated" print("###################") print(footprint_name, "in", lib_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) if Keepout.DEBUG: kicad_modg = Translation(0.0, 0.0) else: kicad_modg = Translation(-rowdist if isSocket and param.num_pin_rows > 1 else -param.pins_offset, 0.0) kicad_mod.append(kicad_modg) # create layer canvases silk = Layer(kicad_modg, 'F.SilkS') fab = Layer(kicad_modg, 'F.Fab') crt = Layer(kicad_modg, 'F.CrtYd', offset=0.5) # offset 0.5 for connectors pads = PadLayer(kicad_modg, pad, Pad.TYPE_THT, Pad.SHAPE_OVAL, shape_first=Pad.SHAPE_RECT, drill=param.pin_drill, x_offset=param.pins_offset) keepout = Keepout(silk) if Keepout.DEBUG: kicad_mod.setSolderMaskMargin(silk.getSoldermaskMargin()) rmh = param.pin_pitch / 2.0 r_dist = rowdist * (param.num_pin_rows - 1) h_fab = param.num_pins * param.pin_pitch + param.body_overlength w_fab = param.body_width t_fab = -rmh - param.body_overlength / 2.0 h_slk = h_fab + silk.offset * 2.0 w_slk = max(w_fab + silk.offset * 2.0, r_dist - pad[0] - silk.offset * 4.0) t_slk = t_fab - silk.offset w_crt = max(param.body_width, r_dist + pad[0]) + crt.offset * 2.0 h_crt = max(h_fab, (param.num_pins - 1) * param.pin_pitch + pad[1]) + crt.offset * 2.0 t_crt = t_fab - crt.offset c_ofs = 0.0 if param.num_pin_rows == 1 else rmh if param.num_pin_rows == 1: r_dist = rowdist # create pads y = 0.0 for r in range(1, param.num_pins + 1): x = rowdist if isSocket and param.num_pin_rows > 1 else 0.0 for c in range(1, param.num_pin_rows + 1): pads.add(x, y) x = x + (-rowdist if isSocket and param.num_pin_rows > 1 else rowdist) y += param.pin_pitch # add pads to silk keepout keepout.addPads() keepout.debug_draw() # add text to silk layer silk.goto(c_ofs, t_crt - silk.txt_offset)\ .text('reference', 'REF**')\ .setOrigin(-w_slk / 2.0 + c_ofs, t_slk) # add fab layer bevel = Layer.getBevel(h_fab, w_fab) fab.goto(c_ofs, h_crt + t_crt + fab.txt_offset)\ .text('value', footprint_name)\ .goto(c_ofs, h_fab / 2.0 + t_fab)\ .setTextDefaults(max_size=1.0)\ .setTextSize(0.6 * (h_fab if param.num_pins == 1 and param.num_pin_rows <= 2 else w_fab))\ .text('user', '%R', rotation=0 if param.num_pins == 1 and param.num_pin_rows <= 2 else 90)\ .setOrigin(-w_fab / 2.0 + c_ofs, t_fab)\ .rect(w_fab, h_fab, bevel=(0.0 if isSocket else bevel, bevel if isSocket else 0.0, 0.0, 0.0), origin="topLeft") # continue with silkscreen pin1 = keepout.getPadBB(1) # if isSocket and param.pins_offset > 0.0: # for 1.00 mm sockets # w_slk = w_slk / 2.0 + (pin1.width / 2.0 + pin1.x) f = -1 if isSocket else 1 if param.num_pin_rows == 1: silk.jump(w_slk if isSocket else 0.0, -t_slk + rmh) if param.num_pins == 1: silk.down(silk.offset, draw=False)\ .right(f * w_slk)\ .up(silk.line_width)\ .jump(-f * w_slk, silk.line_width)\ .up(silk.line_width) else: silk.rect(f * w_slk, h_slk - rmh + t_slk, origin="topLeft") else: if isSocket: silk.right(w_slk, draw=False) silk.right(f * w_slk / 2.0, draw=False)\ .right(f * w_slk / 2.0)\ .down(h_slk)\ .left(f * w_slk)\ .up(h_slk + t_slk - rowdist / 2.0)\ .right(f * w_slk / 2.0)\ .up(-t_slk + rowdist / 2.0) # add pin1 marker silk.goto(max(pin1.x - f * pin1.width / 2.0, w_slk / 2.0 + c_ofs), pin1.y)\ .up(max(-t_slk, pin1.height / 2.0))\ .right(f * (silk.x - pin1.x)) # add courtyard crt.setOrigin(-w_crt / 2.0 + c_ofs, t_crt)\ .rect(w_crt, h_crt, origin="topLeft") # add model kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + ".3dshapes/" + footprint_name + ".wrl")) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(root_dir.saveTo(lib_name) + footprint_name + '.kicad_mod') # # <-->pack_offset # <--------------pack_width---------------> # <-rowdist> # +---------------------------------------+ ---+ # | | OOO OOO | ^ # | | OOO ==== OOO | ^ pin_width # | | OOO OOO | v # +---------------------------------------+ pin_pitch # | | OOO OOO | # | | OOO ==== OOO v # | | OOO OOO # +---------------------------------------+ # class pinSocketHorizontalTHT (object): def __init__(self, params): self.make_me = params.type == CaseType.THT and params.pin_style == PinStyle.ANGLED and params.pad_width > 0 self.params = params def makeModelName(self, genericName): return "PinSocket_{0}x{1:02}_P{2:03.2f}mm_Horizontal".format(self.params.num_pin_rows, self.params.num_pins, self.params.pin_pitch) def make(self, tags_additional=[], isSocket=True): param = self.params lib_name ="Connector_PinSocket_{0:03.2f}mm".format(param.pin_pitch) footprint_name = self.makeModelName("") description = "Through hole angled socket strip, {0}x{1:02}, {2:03.2f}mm pitch, {3}mm socket length"\ .format(param.num_pin_rows, param.num_pins, param.pin_pitch, param.body_width) tags = "Through hole angled socket strip THT {0}x{1:02} {2:03.2f}mm".format(param.num_pin_rows, param.num_pins, param.pin_pitch) tags += txt_tag[param.num_pin_rows] description += txt_descr[param.num_pin_rows] pad = [param.pad_length, param.pad_width] rowdist = param.pin_pitch if len(tags_additional) > 0: for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t if len(param.datasheet) > 0: description += " (" + param.datasheet + ")" description += ", script generated" print("###################") print(footprint_name, "in", lib_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 kicad_modg = Translation(0, 0) kicad_mod.append(kicad_modg) # create layer canvases silk = Layer(kicad_modg, 'F.SilkS') fab = Layer(kicad_modg, 'F.Fab') crt = Layer(kicad_modg, 'F.CrtYd', offset=0.5) # offset 0.5 for connectors pads = PadLayer(kicad_modg, pad, Pad.TYPE_THT, Pad.SHAPE_OVAL, shape_first=Pad.SHAPE_RECT, drill=param.pin_drill) keepout = Keepout(silk) if Keepout.DEBUG: kicad_mod.setSolderMaskMargin(silk.getSoldermaskMargin()) rmh = param.pin_pitch / 2.0 r_dist = rowdist * (param.num_pin_rows - 1) h_fab = (param.num_pins - 1) * param.pin_pitch + param.pin_pitch w_fab = -param.body_width l_fab = -(r_dist + param.body_offset) t_fab = -rmh h_slk = h_fab + silk.offset * 2.0 w_slk = w_fab - silk.offset * 2.0 l_slk = l_fab + silk.offset t_slk = t_fab - silk.offset w_crt = -(rmh + r_dist + param.body_offset + param.body_width + crt.offset * 2.0) h_crt = h_fab + crt.offset * 2.0 l_crt = rmh + crt.offset t_crt = -rmh - crt.offset # create pads y = 0.0 for r in range(1, param.num_pins + 1): x = 0.0 for c in range(1, param.num_pin_rows + 1): pads.add(x, y) x -= rowdist y += param.pin_pitch # add pads to silk keepout keepout.addPads() keepout.debug_draw() # add text to silk silk.goto(l_crt + w_crt / 2.0, t_crt - silk.txt_offset)\ .text('reference', 'REF**') # create FAB-layer bevel = min(Layer.getBevel(h_fab, abs(w_fab)), -t_fab - param.pin_width / 2.0) fab.goto(l_fab + w_fab / 2.0, (h_fab - param.pin_pitch) / 2.0)\ .text('user', '%R', rotation=(90 if h_fab >= -w_fab else 0))\ .rect(-w_fab, h_fab, bevel=(0.0, bevel, 0.0, 0.0))\ .goto(l_crt + w_crt / 2.0, h_crt + t_crt + fab.txt_offset)\ .text('value', footprint_name) # add pin markers fab.goto(l_fab / 2.0, 0.0) for r in range(1, param.num_pins + 1): fab.rect(l_fab, param.pin_width, draw=(True, False, True, True))\ .down(param.pin_pitch, False) # continue silk layer, set origin and fill pin1 rectangle silk.setOrigin(l_fab + w_slk + silk.offset, t_slk)\ .jump(0.0, -t_slk - rmh)\ .fillrect(-w_slk, param.pin_pitch + silk.offset + (silk.offset if param.num_pins == 1 else 0.0))\ pw = param.pin_width + silk.offset * 2.0 # add pin markers silk.goto(l_slk / 2.0, 0.0) for r in range(1, param.num_pins + 1): silk.rect(l_slk, pw, draw=(True, False, True, False))\ .down(param.pin_pitch, False) #add separation lines silk.goHome()\ .jump(0.0, silk.line_width / 2.0) for r in range(1, param.num_pins + 1): silk.right(-w_slk, r != 1)\ .jump(w_slk, param.pin_pitch) # add outline silk.goHome()\ .rect(-w_slk, h_slk, origin='topLeft') pin1 = keepout.getPadBB(1) # add pin1 marker silk.goto(pin1.x + pin1.width / 2.0, pin1.y)\ .up(max(-t_slk, pin1.height / 2.0))\ .left(silk.x - pin1.x) # create courtyard crt.setOrigin(l_crt + w_crt / 2.0, t_crt + h_crt / 2.0)\ .rect(w_crt, h_crt) # add model kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + ".3dshapes/" + footprint_name + ".wrl")) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(root_dir.saveTo(lib_name) + footprint_name + '.kicad_mod') class pinSocketVerticalSMD (object): def __init__(self, params): self.make_me = params.type == 'SMD' and params.pad_width > 0 self.params = params def makeModelName(self, genericName): genericName = "PinSocket_{0}x{1:02}_P{2:03.2f}mm_Vertical_SMD".format(self.params.num_pin_rows, self.params.num_pins, self.params.pin_pitch) return genericName + (("_Pin1Right" if self.params.pin1start_right else "_Pin1Left") if self.params.num_pin_rows == 1 else "" ) def make(self, tags_additional=[], isSocket=True): param = self.params lib_name ="Connector_PinSocket_{0:03.2f}mm".format(param.pin_pitch) footprint_name = self.makeModelName("") description = "surface-mounted straight socket strip, {0}x{1:02}, {2:03.2f}mm pitch".format(param.num_pin_rows, param.num_pins, param.pin_pitch) tags = "Surface mounted socket strip SMD {0}x{1:02} {2:03.2f}mm".format(param.num_pin_rows, param.num_pins, param.pin_pitch) tags += txt_tag[param.num_pin_rows] description += txt_descr[param.num_pin_rows] pad = [param.pad_length, param.pad_width] rowdist = param.pin_pitch rmx_pad_offset = getPadOffsets(param.pads_lp_width, pad) rmx_pin_length = getPinLength(param.pin_length, param.body_width) if (param.num_pin_rows == 1): if param.pin1start_right: description += ", style 2 (pin 1 right)" tags += " style2 pin1 right" else: description += ", style 1 (pin 1 left)" tags += " style1 pin1 left" if len(tags_additional) > 0: for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t if len(param.datasheet) > 0: description += " (" + param.datasheet + ")" description += ", script generated" print("###################") print(footprint_name, "in", lib_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_mod.setAttribute('smd') # anchor for SMD-symbols is in the center kicad_modg = Translation(0.0, 0.0) kicad_mod.append(kicad_modg) rmh = param.pin_pitch / 2.0 # create layer canvases silk = Layer(kicad_modg, 'F.SilkS') fab = Layer(kicad_modg, 'F.Fab') crt = Layer(kicad_modg, 'F.CrtYd', offset=0.5) # offset 0.5 for connectors pads = PadLayer(kicad_modg, pad, Pad.TYPE_SMT, Pad.SHAPE_RECT, y_offset=(param.num_pins - 1) * -rmh) keepout = Keepout(silk) if Keepout.DEBUG: kicad_mod.setSolderMaskMargin(silk.getSoldermaskMargin()) r_dist = rowdist * (param.num_pin_rows - 1) h_fab = param.num_pins * param.pin_pitch + param.body_overlength w_fab = param.body_width t_fab = -param.body_overlength / 2.0 h_slk = h_fab + silk.offset * 2.0 w_slk = max(w_fab + silk.offset * 2.0, r_dist - pad[0] - silk.offset * 4.0) # l_slk = (r_dist - w_slk) / 2.0 # t_slk = -param.body_overlength - silk.offset h_crt = max(h_fab, (param.num_pins - 1) * param.pin_pitch + pad[1]) + crt.offset * 2.0 w_crt = max(param.body_width, rmx_pad_offset * 2.0 + pad[0]) + crt.offset * 2.0 cleft = range(1, param.num_pins, 2) if param.pin1start_right else range(0, param.num_pins, 2) cright = range(0, param.num_pins, 2) if param.pin1start_right else range(1, param.num_pins, 2) even_pins = param.num_pins % 2.0 == 0.0 # create pads if param.num_pin_rows == 1: for y in cleft: pads.add(-rmx_pad_offset, y * param.pin_pitch, number=y + 1) for y in cright: pads.add(rmx_pad_offset, y * param.pin_pitch, number=y + 1) elif param.num_pin_rows == 2: f = 1.0 if isSocket else -1.0 for y in range(0,param.num_pins): pads.add(f * rmx_pad_offset, y * param.pin_pitch)\ .add(f * -rmx_pad_offset, y * param.pin_pitch) # add pads to silk keepout keepout.addPads() keepout.debug_draw() # add text and outline to silk layer silk.goto(0.0, -(h_crt / 2.0) - silk.txt_offset)\ .text('reference', 'REF**')\ .setOrigin(-w_slk / 2.0, -h_slk / 2.0)\ .rect(w_slk, h_slk, origin = "topLeft") # pin1 marker pad1 = keepout.getPadBB(1) f = 1 if isSocket ^ (not param.pin1start_right) else -1 silk.gotoY(pad1.y)\ .jump(w_slk if f == 1 else 0.0, -pad1.height / 2.0)\ .right(f * (pad[0] - silk.line_width) / 2.0 - (silk.x - pad1.x)) # add text and outline to fab layer bevel = min(Layer.getBevel(h_fab, w_fab), -t_fab + rmh + param.pin_width / 2.0) fab.down((h_crt) / 2.0 + fab.txt_offset, draw=False)\ .text('value', footprint_name)\ .goHome()\ .setTextDefaults(max_size=1.0)\ .setTextSize(0.6 * (h_fab if param.num_pins == 1 and param.num_pin_rows <= 2 else w_fab))\ .text('user', '%R', rotation=(90 if h_fab >= w_fab else 0))\ .rect(w_fab, h_fab, bevel=(0.0 if param.pin1start_right else bevel, bevel if param.pin1start_right else 0.0, 0.0, 0.0))\ .setOrigin(-w_fab / 2.0, -h_fab / 2.0) # add pin markers to fab layer trl = w_fab + rmx_pin_length if param.num_pin_rows == 2: fab.jump(-rmx_pin_length / 2.0, -t_fab + rmh) for r in range(1, param.num_pins + 1): fab.rect(rmx_pin_length, param.pin_width, draw=(True, False, True, True))\ .right(trl, draw=False)\ .rect(rmx_pin_length, param.pin_width, draw=(True, True, True, False))\ .left(trl, draw=False)\ .down(param.pin_pitch, draw=False) elif param.pin1start_right: trl = -trl fab.jump(w_fab + rmx_pin_length / 2.0, -t_fab + rmh) for c in cright: fab.rect(rmx_pin_length, param.pin_width, draw=(True, True, True, False))\ .jump(trl, param.pin_pitch) if even_pins or c != cright[-1]: fab.rect(rmx_pin_length, param.pin_width, draw=(True, False, True, True))\ .jump(-trl, param.pin_pitch) else: fab.jump(-rmx_pin_length / 2.0, -t_fab + rmh) for c in cleft: fab.rect(rmx_pin_length, param.pin_width, draw=(True, False, True, True))\ .jump(trl, param.pin_pitch) if even_pins or c != cleft[-1]: fab.rect(rmx_pin_length, param.pin_width, draw=(True, True, True, False))\ .jump(-trl, param.pin_pitch) # add courtyard crt.rect(w_crt, h_crt) # add model kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + ".3dshapes/" + footprint_name + ".wrl")) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(root_dir.saveTo(lib_name) + footprint_name + '.kicad_mod') ### EOF ### ================================================ FILE: scripts/Connectors_DSub/make_dsubs.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_dsub import * # NOQA if __name__ == '__main__': HighDensity=False rmx=2.77 rmy=2.84 rmy_unboxed2=2.54 pindrill=1.0 pad=1.6 mountingdrill=3.2 mountingpad=4 side_angle_degree=10 conn_cornerradius=1.6 outline_cornerradius=1 can_height_male=6 can_height_female=6.17 shieldthickness=0.4 backcan_height=4.5 smaller_backcan_height=2.8 soldercup_length=2.9 soldercup_diameter=1.2 soldercup_padsize=[2*rmx/3,soldercup_length*1.2] soldercup_pad_edge_offset=0.25 smaller_backcan_offset=1 nut_diameter=5 nut_length=5 tags_additional=[] lib_name="${KISYS3DMOD}/Connectors_DSub" classname="DSUB" classname_description="D-Sub connector" webpage="https://disti-assets.s3.amazonaws.com/tonar/files/datasheets/16730.pdf" # 0, 1, 2, 3, 4, 5, 6 # pins, mounting_dist, outline_sizex, outlinesize_y, connwidth, connheight_male, connheight_female sizes_table=[ [ 9, 25, 30.85, 12.50, 16.3, 8.3, 7.9 ], [ 15, 33.30, 39.20, 12.50, 24.6, 8.3, 7.9 ], [ 25, 47.10, 53.10, 12.50, 38.3, 8.3, 7.9 ], [ 37, 63.50, 69.40, 12.50, 54.8, 8.3, 7.9 ], ] for data in sizes_table: makeDSubStraight(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[5], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) makeDSubStraight(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[6], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) makeDSubStraight(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[5], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) makeDSubStraight(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[6], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) makeDSubEdge(pins=data[0], isMale=True, rmx=rmx, pad=soldercup_padsize, mountingdrill=mountingdrill, mountingdistance=data[1], shield_width=data[2], shieldthickness=shieldthickness, connwidth=data[4], can_height=can_height_male, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height, smaller_backcan_offset=smaller_backcan_offset, smaller_backcan_height=smaller_backcan_height, soldercup_length=soldercup_length, soldercup_diameter=soldercup_diameter, soldercup_pad_edge_offset=soldercup_pad_edge_offset, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) makeDSubEdge(pins=data[0], isMale=False, rmx=rmx, pad=soldercup_padsize, mountingdrill=mountingdrill, mountingdistance=data[1], shield_width=data[2], shieldthickness=shieldthickness, connwidth=data[4], can_height=can_height_female, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height, smaller_backcan_offset=smaller_backcan_offset, smaller_backcan_height=smaller_backcan_height, soldercup_length=soldercup_length, soldercup_diameter=soldercup_diameter, soldercup_pad_edge_offset=soldercup_pad_edge_offset, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) # boxed angled # mounting_pcb_distance, pin_pcb_distance angled_distances=[ [ 7.88, 5.34 ], [ 9.52, 8.10 ], [ 11.72, 10.30 ], [ 16.38, 14.96 ], [ 8.60, 14.96 ], ] for data in sizes_table: for angled_distance in angled_distances: mounting_pcb_distance=angled_distance[0]-shieldthickness pin_pcb_distance=angled_distance[1]-shieldthickness backbox_height=max(pin_pcb_distance+rmy+pad/2, mounting_pcb_distance+mountingpad/2)+1 makeDSubAngled(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=mounting_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, can_width=data[4], can_height=can_height_male, backbox_width=data[2], backbox_height=backbox_height, nut_diameter=nut_diameter, nut_length=nut_length, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) makeDSubAngled(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=mounting_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, can_width=data[4], can_height=can_height_female, backbox_width=data[2], backbox_height=backbox_height, nut_diameter=nut_diameter, nut_length=nut_length, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) #makeDSubAngled(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=mounting_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, can_width=data[4], can_height=can_height_male, backbox_width=data[2], backbox_height=backbox_height, nut_diameter=nut_diameter, nut_length=nut_length, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) #makeDSubAngled(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=mounting_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, can_width=data[4], can_height=can_height_female, backbox_width=data[2], backbox_height=backbox_height, nut_diameter=nut_diameter, nut_length=nut_length, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage) # unboxed angled webpageunboxed='http://docs-europe.electrocomponents.com/webdocs/1585/0900766b81585df2.pdf' backcan_height_unboxed=4.1 pin_pcb_distance=9.4 mounting_pcb_distance=0 for data in sizes_table: makeDSubAngled(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_male, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed) makeDSubAngled(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=rmx, rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_female, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed) # alternatice y-pin-pitch makeDSubAngled(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=rmx, rmy=rmy_unboxed2, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_male, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed) makeDSubAngled(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=rmx, rmy=rmy_unboxed2, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_female, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed) HighDensity=True rmy=1.98 # pins, mounting_dist, outline_sizex, outlinesize_y, connwidth, connheight_male, connheight_female, rmx, HighDensityOffsetMidLeft sizes_table=[ [ 15, 25, 30.85, 12.50, 16.3, 8.3, 7.9, 2.29, 7.04 ], [ 26, 33.30, 39.20, 12.50, 24.6, 8.3, 7.9, 2.29, 6.88 ], [ 44, 47.10, 53.10, 12.50, 38.3, 8.3, 7.9, 2.29, 6.88 ], [ 62, 63.50, 69.40, 12.50, 54.8, 8.3, 7.9, 2.41, 7.00 ], ] for data in sizes_table: makeDSubStraight(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[5], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage, HighDensityOffsetMidLeft=data[8]) makeDSubStraight(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[6], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage, HighDensityOffsetMidLeft=data[8]) #makeDSubStraight(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[5], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage, HighDensityOffsetMidLeft=data[8]) #makeDSubStraight(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], outline_size=[data[2],data[3]], outline_cornerradius=outline_cornerradius, connwidth=data[4], side_angle_degree=side_angle_degree, connheight=data[6], conn_cornerradius=conn_cornerradius, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage, HighDensityOffsetMidLeft=data[8]) # mounting_pcb_distance, pin_pcb_distance, backbox_height angled_distances=[ [ 5.34, 3.43, 8.6 ], [ 11.29, 8.75, 0.0 ], ] for data in sizes_table: for angled_distance in angled_distances: mounting_pcb_distance=angled_distance[0]-shieldthickness pin_pcb_distance=angled_distance[1]-shieldthickness if angled_distance[2]>0: backbox_height=angled_distance[2] else: backbox_height=max(pin_pcb_distance+rmy+pad/2, mounting_pcb_distance+mountingpad/2)+1 makeDSubAngled(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=mounting_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, can_width=data[4], can_height=can_height_male, backbox_width=data[2], backbox_height=backbox_height, nut_diameter=nut_diameter, nut_length=nut_length, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage, HighDensityOffsetMidLeft=data[8]) makeDSubAngled(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=mountingdrill, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=mounting_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, can_width=data[4], can_height=can_height_male, backbox_width=data[2], backbox_height=backbox_height, nut_diameter=nut_diameter, nut_length=nut_length, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpage, HighDensityOffsetMidLeft=data[8]) # unboxed angled webpageunboxed='http://docs-europe.electrocomponents.com/webdocs/1585/0900766b81585df2.pdf' backcan_height_unboxed=4.1 pin_pcb_distance=9.4 mounting_pcb_distance=0 for data in sizes_table: makeDSubAngled(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_male, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed, HighDensityOffsetMidLeft=data[8]) makeDSubAngled(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=data[7], rmy=rmy, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_female, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed, HighDensityOffsetMidLeft=data[8]) makeDSubAngled(pins=data[0], isMale=True, HighDensity=HighDensity, rmx=data[7], rmy=rmy_unboxed2, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_male, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed, HighDensityOffsetMidLeft=data[8]) makeDSubAngled(pins=data[0], isMale=False, HighDensity=HighDensity, rmx=data[7], rmy=rmy_unboxed2, pindrill=pindrill, pad=pad, pin_pcb_distance=pin_pcb_distance, mountingdrill=0, mountingpad=mountingpad, mountingdistance=data[1], mounting_pcb_distance=pin_pcb_distance, shield_width=data[2], shield_thickness=shieldthickness, backbox_width=0, backbox_height=0, can_width=data[4], can_height=can_height_female, backcan_width=data[4]+2*shieldthickness, backcan_height=backcan_height_unboxed, nut_diameter=0, nut_length=0, tags_additional=tags_additional, lib_name=lib_name, classname=classname, classname_description=classname_description, webpage=webpageunboxed, HighDensityOffsetMidLeft=data[8]) ================================================ FILE: scripts/Converter_DCDC/Converter_DCDC.py ================================================ #!/usr/bin/env python3 import sys import os import re # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) # load scripts sys.path.append(os.path.join(sys.path[0], "..")) from KicadModTree import * from general.StandardBox import * def qfn(args): extraffablines = [] footprint_name = args["name"] description = args["description"] datasheet = args["description"] fptag = args["tags"] SmdTht = args["smd_tht"] at = args["at"] size = args["size"] pins = args["pins"] extratexts = args["extratexts"] dir3D = 'Converter_DCDC.3dshapes' f = Footprint(footprint_name) file3Dname = "${KISYS3DMOD}/" + dir3D + "/" + footprint_name + ".wrl" words = footprint_name.split("_") if words[-1].lower().startswith('handsolder'): words[-1] = '' ff = '_'.join(words) file3Dname = "${KISYS3DMOD}/" + dir3D + "/" + ff + ".wrl" f.append(StandardBox(footprint=f, description=description, datasheet=datasheet, at=at, size=size, tags=fptag, SmdTht=SmdTht, extratexts=extratexts, pins=pins, file3Dname=file3Dname )) # # # file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(qfn) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("description", type=str, required=True) parser.add_parameter("datasheet", type=str, required=True) parser.add_parameter("tags", type=str, required=True) parser.add_parameter("smd_tht", type=str, required=False, default='tht') parser.add_parameter("at", type=list, required=True) parser.add_parameter("size", type=list, required=False) parser.add_parameter("pins", type=list, required=True) parser.add_parameter("extratexts", type=list, required=True) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Converter_DCDC/Converter_DCDC.yml ================================================ Converter_DCDC_Murata_NCS1SxxxxSC_THT: description: "Murata NCS1SxxxxSC https://power.murata.com/data/power/ncl/kdc_ncs1.pdf" datasheet: "https://power.murata.com/data/power/ncl/kdc_ncs1.pdf" tags: "Murata NCS1SxxxxSC" extratexts: [[-3.0, 0, "", "F.SilkS", 1.0, 1.0]] at: [-2.27, 3.195] size: [21.87, 8.2] pins: [["thtr", "1", 0, 0, 1.70, 2.0, 1.0], ["thtr", "2", 2.54, 0, 1.70, 2.0, 1.0], ["thtr", "3", 5.12, 0, 1.70, 2.0, 1.0], ["thtr", "6", 12.7, 0, 1.70, 2.0, 1.0], ["thtr", "7", 15.24, 0, 1.70, 2.0, 1.0]] ================================================ FILE: scripts/Converter_DCDC/XP_Power_SF_THT.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree import argparse import yaml from helpers import * from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields series = "SF" manufacturer = 'XP_POWER' #Designed to support SF_IA, SF_IH, SF_ITX, SF_ITQ series, and potentially more fab_pin1_marker_type = 1 pin1_marker_offset = 0.3 pin1_marker_linelen = 1.25 drill_size = 0.85#0.5 pin diameter, 0.35 pin pitch tolerance pad_to_pad_clearance = 0.69 pad_copper_y_solder_length = 0.5 #How much copper should be in y direction? min_annular_ring = 0.15 xpitch = 7.62 ypitch = 2.54 def generate_one_footprint(fpid, rows, datasheet, configuration): pins = [] if fpid == "IAxxxxS" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 6.09 casemaxlength = 19.30 x_max = 1.40 x_min = x_max - (casemaxwidth - casetolerance) y_min = -1.53 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 4, 5, 6] elif fpid == "IA48xxS" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 7.20 casemaxlength = 19.30 x_max = 1.40 x_min = x_max - (casemaxwidth - casetolerance) y_min = -1.53 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 4, 5, 6] elif fpid == "IAxxxxD" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 4, 6, 7] elif fpid == "IA48xxD" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 4, 6, 7] elif fpid == "IHxxxxS" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 7.20 casemaxlength = 19.5 x_max = 1.25 x_min = x_max - (casemaxwidth - casetolerance) y_min = -2.29 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 4, 5, 6] elif fpid == "IHxxxxSH" and rows == "SIP" : casetolerance = 0.5 casemaxwidth = 7.62 casemaxlength = 19.5 x_max = 1.25 x_min = x_max - (casemaxwidth - casetolerance) y_min = -2.29 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 4, 5, 6] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 5, 6, 7] elif fpid == "IHxxxxD" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 4, 6, 7] elif fpid == "IHxxxxDH" and rows == "DIP" : casetolerance = 0.5 casemaxwidth = 10.16 casemaxlength = 20.32 x_min = -(casemaxwidth-casetolerance-xpitch)/2 x_max = x_min + (casemaxwidth - casetolerance) y_min = -(casemaxlength-casetolerance-15.24)/2 y_max = y_min + (casemaxlength - casetolerance) pins = [1, 2, 3, 4, 5, 6] xpos = [1, 1, 2, 2, 2, 2] ypos = [1, 7, 1, 5, 7, 6] elif fpid == "ITQxxxxS-H" and rows == "SIP" : casetolerance = 0.5 casewidth = 9.20 caselength = 21.85 x_max = 3.20 x_min = x_max - casewidth y_min = -(caselength - 17.78)/2 y_max = y_min + caselength pins = [1, 2, 3, 6, 7, 8] xpos = [1, 1, 1, 1, 1, 1] ypos = [1, 2, 3, 6, 7, 8] elif fpid == "ITxxxxxS" and rows == "SIP" : casetolerance = 0.5 casewidth = 9.20 caselength = 21.85 x_max = 3.20 x_min = x_max - casewidth y_min = -(caselength - 17.78)/2 y_max = y_min + caselength pins = [1, 2, 3, 6, 7] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 3, 6, 7] elif fpid == "ITXxxxxSA" and rows == "SIP" : casetolerance = 0.5 casewidth = 9.20 caselength = 21.85 x_max = 3.20 x_min = x_max - casewidth y_min = -(caselength - 17.78)/2 y_max = y_min + caselength pins = [1, 2, 6, 7, 8] xpos = [1, 1, 1, 1, 1] ypos = [1, 2, 6, 7, 8] silk_x_min = x_min - configuration['silk_fab_offset'] silk_x_max = x_max + configuration['silk_fab_offset'] silk_y_min = y_min - configuration['silk_fab_offset'] silk_y_max = y_max + configuration['silk_fab_offset'] footprint_name = "Converter_DCDC_XP_POWER-{:s}_THT".format(fpid) ser = "" if fpid.startswith("IA_"): ser="SF_IA" elif fpid.startswith("IH_"): ser="SF_IH" elif fpid.startswith("ITX_"): ser="SF_ITX" elif fpid.startswith("ITQ_"): ser="SF_ITQ" kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("XP_POWER {:s} {:s}, {:s}, ({:s}), generated with kicad-footprint-generator".format(ser,fpid, rows, datasheet)) kicad_mod.setTags("XP_POWER {:s} {:s} {:s} DCDC-Converter".format(ser,fpid,rows)) # create Silkscreen kicad_mod.append(RectLine(start=[silk_x_min,silk_y_min], end=[silk_x_max,silk_y_max], layer='F.SilkS', width=configuration['silk_line_width'])) ########################### Pin 1 marker ################################ poly_pin1_marker = [ {'x':silk_x_min-pin1_marker_offset+pin1_marker_linelen, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset}, {'x':silk_x_min-pin1_marker_offset, 'y':silk_y_min-pin1_marker_offset+pin1_marker_linelen} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.SilkS', width=configuration['silk_line_width'])) if fab_pin1_marker_type == 1: kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker, layer='F.Fab', width=configuration['fab_line_width'])) if fab_pin1_marker_type == 2: poly_pin1_marker_type2 = [ {'x':-1, 'y':y_min}, {'x':0, 'y':y_min+1}, {'x':1, 'y':y_min} ] kicad_mod.append(PolygoneLine(polygone=poly_pin1_marker_type2, layer='F.Fab', width=configuration['fab_line_width'])) ########################## Fab Outline ############################### kicad_mod.append(RectLine(start=[x_min,y_min], end=[x_max,y_max], layer='F.Fab', width=configuration['fab_line_width'])) ############################# CrtYd ################################## part_x_min = x_min part_x_max = x_max part_y_min = y_min part_y_max = y_max #Note, we use the connector courtyard clearance of 0.5 mm because the unusually large case tolerance of 0.5mm of XP Powers DC DC converters cx1 = roundToBase(part_x_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy1 = roundToBase(part_y_min-configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cx2 = roundToBase(part_x_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) cy2 = roundToBase(part_y_max+configuration['courtyard_offset']['connector'], configuration['courtyard_grid']) kicad_mod.append(RectLine( start=[cx1, cy1], end=[cx2, cy2], layer='F.CrtYd', width=configuration['courtyard_line_width'])) ############################# Pads ################################## pad_size = [ypitch - pad_to_pad_clearance, drill_size + 2*pad_copper_y_solder_length] if pad_size[0] - drill_size < 2*min_annular_ring: pad_size[0] = drill_size + 2*min_annular_ring optional_pad_params = {} if configuration['kicad4_compatible']: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_RECT else: optional_pad_params['tht_pad1_shape'] = Pad.SHAPE_ROUNDRECT for i in range(len(pins)): pshape = Pad.SHAPE_OVAL if pins[i] == 1: pshape = Pad.SHAPE_RECT kicad_mod.append(Pad(number=pins[i], type=Pad.TYPE_THT, shape=pshape, at=[(xpos[i]-1)*xpitch, (ypos[i]-1)*ypitch], size=pad_size, drill=drill_size, layers=Pad.LAYERS_THT, **optional_pad_params)) ######################### Text Fields ############################### text_center_y = 1.5 body_edge={'left':part_x_min, 'right':part_x_max, 'top':part_y_min, 'bottom':part_y_max} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':cy1, 'bottom':cy2}, fp_name=footprint_name, text_y_inside_position=text_center_y) model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = configuration['lib_name_format_string'].format(series=ser) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=footprint_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) print(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='conv_config_KLCv3.yaml') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) configuration['kicad4_compatible'] = args.kicad4_compatible generate_one_footprint("IA48xxS" ,"SIP","https://www.xppower.com/pdfs/SF_IA.pdf", configuration) generate_one_footprint("IAxxxxS" ,"SIP","https://www.xppower.com/pdfs/SF_IA.pdf", configuration) generate_one_footprint("IA48xxD" ,"DIP","https://www.xppower.com/pdfs/SF_IA.pdf", configuration) generate_one_footprint("IAxxxxD" ,"DIP","https://www.xppower.com/pdfs/SF_IA.pdf", configuration) generate_one_footprint("IHxxxxS" ,"SIP","https://www.xppower.com/pdfs/SF_IH.pdf", configuration) generate_one_footprint("IHxxxxSH" ,"SIP","https://www.xppower.com/pdfs/SF_IH.pdf", configuration) generate_one_footprint("IHxxxxD" ,"DIP","https://www.xppower.com/pdfs/SF_IH.pdf", configuration) generate_one_footprint("IHxxxxDH" ,"DIP","https://www.xppower.com/pdfs/SF_IH.pdf", configuration) generate_one_footprint("ITQxxxxS-H","SIP","https://www.xppower.com/pdfs/SF_ITQ.pdf", configuration) generate_one_footprint("ITxxxxxS" ,"SIP","https://www.xppower.com/pdfs/SF_ITX.pdf https://www.xppower.com/pdfs/SF_ITQ.pdf", configuration) generate_one_footprint("ITXxxxxSA", "SIP","https://www.xppower.com/pdfs/SF_ITX.pdf", configuration) ================================================ FILE: scripts/Converter_DCDC/conv_config_KLCv3.yaml ================================================ lib_name_format_string_full: 'Converter_DCDC_{man:s}_{series:s}{suffix:s}' lib_name_format_string: 'Converter_DCDC' lib_name_specific_function_format_string: 'Converter_DCDC_{category:s}' ================================================ FILE: scripts/Crystals_Resonators_SMD/make_crystal_smd.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_crystals import * if __name__ == '__main__': standardtags="SMD SMT crystal" standardtagsres="SMD SMT ceramic resonator filter" # common settings makeSMDCrystalAndHand(footprint_name="Crystal_SMD_Abracon_ABM3", addSizeFootprintName=True, pins=2, pad_sep_x=2.2+1.9, pad_sep_y=0, pad=[1.9,2.4], pack_width=5, pack_height=3.2, pack_bevel=0.2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=1, description="Abracon Miniature Ceramic Smd Crystal ABM3 http://www.abracon.com/Resonators/abm3.pdf", tags=standardtags+"", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_Abracon_ABM3B", addSizeFootprintName=True, pins=4, pad_sep_x=4, pad_sep_y=2.4, pad=[1.8,1.2], pack_width=5, pack_height=3.2, pack_bevel=0.2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=1, description="Abracon Miniature Ceramic Smd Crystal ABM3B http://www.abracon.com/Resonators/abm3b.pdf", tags=standardtags+"", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_Abracon_ABM3C", addSizeFootprintName=True, pins=4, pad_sep_x=3.8, pad_sep_y=2.3, pad=[1.6,1.3], pack_width=5, pack_height=3.2, pack_bevel=0.2, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=1, description="Abracon Miniature Ceramic Smd Crystal ABM3C http://www.abracon.com/Resonators/abm3c.pdf", tags=standardtags+"", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_Abracon_ABM8G", addSizeFootprintName=True, pins=4, pad_sep_x=2.2, pad_sep_y=1.7, pad=[1.4,1.2], pack_width=3.2, pack_height=2.5, pack_bevel=0.2, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=1, description="Abracon Miniature Ceramic Smd Crystal ABM8G http://www.abracon.com/Resonators/ABM8G.pdf", tags=standardtags+"", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_FA238", addSizeFootprintName=True, pins=4, pad_sep_x=2.2, pad_sep_y=1.6, pad=[1.4, 1.2], pack_width=3.2, pack_height=2.5, pack_bevel=0.1, description="crystal Epson Toyocom FA-238 series http://www.mouser.com/ds/2/137/1721499-465440.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[0.24,0.24,0.24], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_FA238V", addSizeFootprintName=True, pins=4, pad_sep_x=2.4, pad_sep_y=1.9, pad=[1.4, 1.2], pack_width=3.2, pack_height=2.5, pack_bevel=0.1, description="crystal Epson Toyocom FA-238 series http://www.mouser.com/ds/2/137/1721499-465440.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_TSX3225", addSizeFootprintName=True, pins=4, pad_sep_x=2.2, pad_sep_y=1.6, pad=[1.4, 1.15], pack_width=3.2, pack_height=2.5, pack_bevel=0.1, description="crystal Epson Toyocom TSX-3225 series http://www.mouser.com/ds/2/137/1721499-465440.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[0.24,0.24,0.24], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_FOX_FE", addSizeFootprintName=True, pins=2, pad_sep_x=6.3, pad_sep_y=0, pad=[2.2, 2.4], pack_width=7.5, pack_height=5, pack_bevel=0,hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.8, description="crystal Ceramic Resin Sealed SMD http://www.foxonline.com/pdfs/fe.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_0603", addSizeFootprintName=True, pins=2, pad_sep_x=4.4, pad_sep_y=0, pad=[1.9,2.5], pack_width=6, pack_height=3.5, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD0603/2 http://www.petermann-technik.de/fileadmin/petermann/pdf/SMD0603-2.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_0603", addSizeFootprintName=True, pins=4, pad_sep_x=4.4, pad_sep_y=2.4, pad=[1.8, 1.4], pack_width=6, pack_height=3.5, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD0603/4 http://www.petermann-technik.de/fileadmin/petermann/pdf/SMD0603-4.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_3225", addSizeFootprintName=True, pins=4, pad_sep_x=2.2, pad_sep_y=1.7, pad=[1.4,1.2], pack_width=3.2, pack_height=2.5, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.4, description="SMD Crystal SERIES SMD3225/4 http://www.txccrystal.com/images/pdf/7m-accuracy.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_2012", addSizeFootprintName=True, pins=2, pad_sep_x=1.4, pad_sep_y=0, pad=[0.6,1.1], pack_width=2, pack_height=1.2, pack_bevel=0, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.4, description="SMD Crystal 2012/2 http://txccrystal.com/images/pdf/9ht11.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_TXC_9HT11", addSizeFootprintName=True, pins=2, pad_sep_x=1.4, pad_sep_y=0, pad=[0.6, 1.1], pack_width=2, pack_height=1.2, pack_bevel=0, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.4, description="SMD Crystal TXC 9HT11 http://txccrystal.com/images/pdf/9ht11.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_TXC_7M", addSizeFootprintName=True, pins=4, pad_sep_x=2.2, pad_sep_y=1.7, pad=[1.4,1.2], pack_width=3.2, pack_height=2.5, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.4, description="SMD Crystal TXC 7M http://www.txccrystal.com/images/pdf/7m-accuracy.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_2016", addSizeFootprintName=True, pins=4, pad_sep_x=1.4, pad_sep_y=1.1, pad=[0.9,0.8], pack_width=2, pack_height=1.6, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD2016/4 http://www.q-crystal.com/upload/5/2015552223166229.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_2520", addSizeFootprintName=True, pins=4, pad_sep_x=1.75, pad_sep_y=1.4, pad=[1.15,1], pack_width=2.5, pack_height=2, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD2520/4 http://www.newxtal.com/UploadFiles/Images/2012-11-12-09-29-09-776.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_2520", addSizeFootprintName=True, pins=4, pad_sep_x=1.75, pad_sep_y=1.4, pad=[1.15, 1], pack_width=2.5, pack_height=2, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD2520/4 http://www.newxtal.com/UploadFiles/Images/2012-11-12-09-29-09-776.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_5032", addSizeFootprintName=True, pins=4, pad_sep_x=3.3, pad_sep_y=2.0, pad=[1.6, 1.3], pack_width=5, pack_height=3.2, pack_bevel=0.2, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD2520/4 http://www.icbase.com/File/PDF/HKC/HKC00061008.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_5032", addSizeFootprintName=True, pins=2, pad_sep_x=3.7, pad_sep_y=0, pad=[2, 2.4], pack_width=5, pack_height=3.2, pack_bevel=0.2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD2520/2 http://www.icbase.com/File/PDF/HKC/HKC00061008.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_7050", addSizeFootprintName=True, pins=4, pad_sep_x=5.9, pad_sep_y=2.7, pad=[2.1,1.7], pack_width=7, pack_height=5, pack_bevel=0.2, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD7050/4 https://www.foxonline.com/pdfs/FQ7050.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_7050", addSizeFootprintName=True, pins=2, pad_sep_x=5.2, pad_sep_y=0, pad=[2.8, 3], pack_width=7, pack_height=5, pack_bevel=0.2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.8, description="SMD Crystal SERIES SMD7050/4 https://www.foxonline.com/pdfs/FQ7050.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Crystal_SMD_FOX_FQ7050", addSizeFootprintName=True, pins=4, pad_sep_x=5.9, pad_sep_y=2.7, pad=[2.1, 1.7], pack_width=7, pack_height=5, pack_bevel=0.2, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.8, description="FOX SMD Crystal SERIES SMD7050/4 https://www.foxonline.com/pdfs/FQ7050.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_FOX_FQ7050", addSizeFootprintName=True, pins=2, pad_sep_x=5.2, pad_sep_y=0, pad=[2.8, 3], pack_width=7, pack_height=5, pack_bevel=0.2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.8, description="FOX SMD Crystal SERIES SMD7050/4 https://www.foxonline.com/pdfs/FQ7050.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_G8", addSizeFootprintName=True, pins=2, pad_sep_x=2.5, pad_sep_y=0, pad=[1,1.8], pack_width=3.2, pack_height=1.5, pack_bevel=0, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal G8", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_HC49-SD", addSizeFootprintName=False, pins=2, style="hc49", pad_sep_x=8.5, pad_sep_y=0, pad=[4.5,2], pack_width=11.4, pack_height=4.7, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal HC-49-SD http://cdn-reichelt.de/documents/datenblatt/B400/xxx-HC49-SMD.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MC156", addSizeFootprintName=True, pins=4, style="dip", pad_sep_x=5.08, pad_sep_y=2.5, pad=[1.2,1.5], pack_width=7.1, pack_height=2.5, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-156 https://support.epson.biz/td/api/doc_check.php?dl=brief_MC-156_en.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MC146", addSizeFootprintName=True, pins=4, style="rect", pad_sep_x=6.3, pad_sep_y=0.9, pad=[1.2,0.6], pack_width=6.7, pack_height=1.5, pack_bevel=0.4, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-146 https://support.epson.biz/td/api/doc_check.php?dl=brief_MC-156_en.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MC306", addSizeFootprintName=True, pins=4, style="dip", pad_sep_x=5.5, pad_sep_y=3.2, pad=[1.3,1.9], pack_width=8, pack_height=3.2, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-306 https://support.epson.biz/td/api/doc_check.php?dl=brief_MC-306_en.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MC405", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=8, pad_sep_y=0, pad=[4.1,4.1], pack_width=9.6, pack_height=4.06, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-405 https://support.epson.biz/td/api/doc_check.php?dl=brief_MC-306_en.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MC406", addSizeFootprintName=True, pins=4, style="rect", pad_sep_x=8, pad_sep_y=2.32, pad=[4.1, 1.52], pack_width=9.6, pack_height=4.06, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-406 https://support.epson.biz/td/api/doc_check.php?dl=brief_MC-306_en.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MA505", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=11.1, pad_sep_y=0, pad=[4.1, 5.6], pack_width=12.7, pack_height=5.08, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-505 http://media.digikey.com/pdf/Data%20Sheets/Epson%20PDFs/MA-505,506.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MA506", addSizeFootprintName=True, pins=4, style="rect", pad_sep_x=11.1, pad_sep_y=3.55, pad=[4.1, 2.05], pack_width=12.7, pack_height=5.08, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-506 http://media.digikey.com/pdf/Data%20Sheets/Epson%20PDFs/MA-505,506.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_SeikoEpson_MA406", addSizeFootprintName=True, pins=4, style="dip", pad_sep_x=9.6, pad_sep_y=3.6, pad=[1.8,1.9], pack_width=11.7, pack_height=4, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Seiko Epson MC-506 http://media.digikey.com/pdf/Data%20Sheets/Epson%20PDFs/MA-505,506.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_EuroQuartz_MT", addSizeFootprintName=True, pins=4, style="rect", pad_sep_x=2.2, pad_sep_y=1.8, pad=[1.3,1], pack_width=3.2, pack_height=2.5, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal EuroQuartz MT series http://cdn-reichelt.de/documents/datenblatt/B400/MT.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_EuroQuartz_X22", addSizeFootprintName=True, pins=4, style="rect", pad_sep_x=1.6, pad_sep_y=1.2, pad=[1.2,1], pack_width=2.5, pack_height=2, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal EuroQuartz X22 series http://cdn-reichelt.de/documents/datenblatt/B400/DS_X22.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_EuroQuartz_MJ", addSizeFootprintName=True, pins=4, style="rect", pad_sep_x=3.7, pad_sep_y=2.3, pad=[1.9, 1.1], pack_width=5, pack_height=3.2, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal EuroQuartz MJ series http://cdn-reichelt.de/documents/datenblatt/B400/MJ.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_EuroQuartz_MQ", addSizeFootprintName=True, pins=4, style="rect", pad_sep_x=6.3, pad_sep_y=2.5, pad=[2.2,1.4], pack_width=7, pack_height=5, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal EuroQuartz MQ series http://cdn-reichelt.de/documents/datenblatt/B400/MQ.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_EuroQuartz_MQ2", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=6.3, pad_sep_y=0, pad=[2.2,2.4], pack_width=7, pack_height=5, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal EuroQuartz MQ2 series http://cdn-reichelt.de/documents/datenblatt/B400/MQ.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_EuroQuartz_EQ161", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=2.5, pad_sep_y=0, pad=[1,1.8], pack_width=3.2, pack_height=1.5, pack_bevel=0.1, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal EuroQuartz EQ161 series http://cdn-reichelt.de/documents/datenblatt/B400/PG32768C.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_MicroCrystal_CC1V-T1A", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=6.3, pad_sep_y=0, pad=[2.3, 4.2], pack_width=8, pack_height=3.7, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal MicroCrystal CC1V-T1A series http://www.microcrystal.com/images/_Product-Documentation/01_TF_ceramic_Packages/01_Datasheet/CC1V-T1A.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_MicroCrystal_CC4V-T1A", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=4.2, pad_sep_y=0, pad=[1.3, 2.2], pack_width=5, pack_height=1.9, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal MicroCrystal CC4V-T1A series http://cdn-reichelt.de/documents/datenblatt/B400/CC4V-T1A.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_MicroCrystal_CC5V-T1A", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=3.4, pad_sep_y=0, pad=[1.1, 1.9], pack_width=4.1, pack_height=1.5, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal MicroCrystal CC5V-T1A series http://cdn-reichelt.de/documents/datenblatt/B400/CC5V-T1A.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_MicroCrystal_CC7V-T1A", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=2.5, pad_sep_y=0, pad=[1,1.8], pack_width=3.2, pack_height=1.5, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal MicroCrystal CC7V-T1A/CM7V-T1A series http://www.microcrystal.com/images/_Product-Documentation/01_TF_ceramic_Packages/01_Datasheet/CC1V-T1A.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_MicroCrystal_CC8V-T1A", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=1.5, pad_sep_y=0, pad=[0.8,1.5], pack_width=2, pack_height=1.2, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal MicroCrystal CC8V-T1A/CM8V-T1A series http://www.microcrystal.com/images/_Product-Documentation/01_TF_ceramic_Packages/01_Datasheet/CC8V-T1A.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Crystal_SMD_MicroCrystal_CM9V-T1A", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=1.2, pad_sep_y=0, pad=[0.6,1.2], pack_width=1.6, pack_height=1.0, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal MicroCrystal CM9V-T1A series http://www.microcrystal.com/images/_Product-Documentation/01_TF_ceramic_Packages/01_Datasheet/CM9V-T1A.pdf", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeCrystal(footprint_name="Crystal_SMD_MicroCrystal_MS3V-T1R", rm=1, pad_size=[1.1,0.6], ddrill=1, pack_width=5.2, pack_height=1.4, pack_rm=0.7, pack_offset=1.2, package_pad=True, package_pad_offset=4.4, package_pad_size=[2.4,1.5], package_pad_add_holes=False, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="flat", pad_style="smd", description="SMD Watch Crystal MicroCrystal MS3V-T1R 5.2mm length 1.4mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/MS3V-T1R.pdf", tags=["MS3V-T1R"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeCrystal(footprint_name="Crystal_SMD_MicroCrystal_MS1V-T1K", rm=2.54, pad_size=[1.6,1], ddrill=1, pack_width=6.1, pack_height=2, pack_rm=1, pack_offset=1.6, package_pad=True, package_pad_offset=5.3, package_pad_size=[2.5, 3], package_pad_add_holes=False, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="flat", pad_style="smd", description="SMD Watch Crystal MicroCrystal MS1V-T1K 6.1mm length 2.0mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/MS1V-T1K.pdf", tags=["MS1V-T1K"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeCrystal(footprint_name="Crystal_SMD_FrontierElectronics_FM206", rm=2.54, pad_size=[1.6,1], ddrill=1, pack_width=6.0, pack_height=1.9, pack_rm=1, pack_offset=1.6, package_pad=True, package_pad_offset=5.3, package_pad_size=[2.5, 3], package_pad_add_holes=False, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="flat", pad_style="smd", description="SMD Watch Crystal FrontierElectronics FM206 6.0mm length 1.9mm diameter http://www.chinafronter.com/wp-content/uploads/2013/12/FM206.pdf", tags=["FM206"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Resonator_SMD", addSizeFootprintName=True, pins=3, style="rect", pad_sep_x=2.5, pad_sep_y=0, pad=[1.4, 3.8], pack_width=7.2, pack_height=3, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Resomator/Filter 7.2x3.0mm, Murata CSTCC8M00G53-R0; 8MHz resonator, SMD, Farnell (Element 14) #1170435, http://www.farnell.com/datasheets/19296.pdf?_ga=1.247244932.122297557.1475167906", tags=standardtagsres + " filter", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Resonator_SMD_Murata_SFECV", addSizeFootprintName=True, pins=3, style="rect", pad_sep_x=2.85, pad_sep_y=0, pad=[1.2, 4], pack_width=6.9, pack_height=2.9, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Resomator/Filter Murata SFECV, http://cdn-reichelt.de/documents/datenblatt/B400/SFECV-107.pdf", tags=standardtagsres + " filter", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Resonator_SMD_Murata_SFSKA", addSizeFootprintName=True, pins=3, style="rect", pad_sep_x=2.5, pad_sep_y=0, pad=[1, 4.8], pack_width=7.9, pack_height=3.8, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Resomator/Filter Murata SFSKA, http://cdn-reichelt.de/documents/datenblatt/B400/SFECV-107.pdf", tags=standardtagsres + " filter", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Resonator_SMD_Murata_TPSKA", addSizeFootprintName=True, pins=3, style="rect", pad_sep_x=2.5, pad_sep_y=0, pad=[1, 4.8], pack_width=7.9, pack_height=3.8, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Resomator/Filter Murata TPSKA, http://cdn-reichelt.de/documents/datenblatt/B400/SFECV-107.pdf", tags=standardtagsres + " filter", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Resonator_SMD_Murata_CDSCB", addSizeFootprintName=True, pins=2, style="rect", pad_sep_x=3, pad_sep_y=0, pad=[1, 2.6], pack_width=4.5, pack_height=2, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Resomator/Filter Murata CDSCB, http://cdn-reichelt.de/documents/datenblatt/B400/SFECV-107.pdf", tags=standardtagsres + " filter", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) ================================================ FILE: scripts/Crystals_Resonators_THT/make_crystal.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_crystals import * if __name__ == '__main__': standardtags="THT crystal" standardtagsres="THT ceramic resonator filter" script3dhc49="crystal_hc49_2pin.py" with open(script3dhc49, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dhc493p="crystal_hc49_3pin.py" with open(script3dhc493p, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dres3="resonator_3pin.py" with open(script3dres3, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dres2="resonator_2pin.py" with open(script3dres2, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dhc49h="crystal_hc49_2pin_hor.py" with open(script3dhc49h, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") # common settings makeCrystalAll(footprint_name="Crystal_AT310_d3.0mm_l10.0mm_Horizontal", rm=2.54, pad_size=1, ddrill=0.5, pack_width=10.5, pack_height=3, pack_rm=1.2, pack_offset=3, package_pad=True, package_pad_offset=3.5, package_pad_size=[10.5,3.2], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="flat", description="Crystal THT AT310 10.0mm-10.5mm length 3.0mm diameter", lib_name="Crystals", tags=["AT310"], offset3d=[1.27/25.4, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_AT310_d3.0mm_l10.0mm_Vertical", rm=2.54, pad_size=1, ddrill=0.5, pack_diameter=3, description="Crystal THT AT310 10.0mm-10.5mm length 3.0mm diameter", lib_name="Crystals", tags=["AT310"], offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalAll(footprint_name="Crystal_C26-LF_d2.1mm_l6.5mm_Horizontal", rm=1.9, pad_size=1, ddrill=0.5, pack_width=6.5, pack_height=2.06, pack_rm=0.7, pack_offset=2, package_pad=True, package_pad_offset=2.5, package_pad_size=[6.5,2.2], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="flat", description="Crystal THT C26-LF 6.5mm length 2.06mm diameter", tags=["C26-LF"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_C26-LF_d2.1mm_l6.5mm_Vertical", rm=1.9, pad_size=1, ddrill=0.5, pack_diameter=2.06, description="Crystal THT C26-LF 6.5mm length 2.06mm diameter", tags=["C26-LF"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalAll(footprint_name="Crystal_C38-LF_d3.0mm_l8.0mm_Horizontal", rm=1.9, pad_size=1, ddrill=0.5, pack_width=8, pack_height=3, pack_rm=1.09, pack_offset=2.5, package_pad=True, package_pad_offset=3, package_pad_size=[8,3], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="flat", description="Crystal THT C38-LF 8.0mm length 3.0mm diameter", tags=["C38-LF"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_C38-LF_d3.0mm_l8.0mm_Vertical", rm=1.9, pad_size=1, ddrill=0.5, pack_diameter=3, description="Crystal THT C38-LF 8.0mm length 3.0mm diameter", tags=["C38-LF"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_Round_d3.0mm_Vertical", rm=1.9, pad_size=1, ddrill=0.5, pack_diameter=3, description="Crystal THT C38-LF 8.0mm length 3.0mm diameter", tags=["C38-LF"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalAll(footprint_name="Crystal_DS26_d2.0mm_l6.0mm_Horizontal", rm=1.9, pad_size=1, ddrill=0.5, pack_width=6, pack_height=2, pack_rm=0.7, pack_offset=2, package_pad=True, package_pad_offset=2.5, package_pad_size=[6,2.5], package_pad_add_holes=True, package_pad_drill_size=[1, 1], package_pad_ddrill=0.5, style="flat", description="Crystal THT DS26 6.0mm length 2.0mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS26"],lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_DS26_d2.0mm_l6.0mm_Vertical", rm=1.9, pad_size=1, ddrill=0.5, pack_diameter=2, description="Crystal THT DS26 6.0mm length 2.0mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS26"],lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_Round_d2.0mm_Vertical", rm=1.9, pad_size=1, ddrill=0.5, pack_diameter=2, description="Crystal THT DS26 6.0mm length 2.0mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS26"],lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalAll(footprint_name="Crystal_DS15_d1.5mm_l5.0mm_Horizontal", rm=1.7, pad_size=1, ddrill=0.5, pack_width=5, pack_height=1.5, pack_rm=0.5, pack_offset=1.5, package_pad=True, package_pad_offset=2, package_pad_size=[5,2], package_pad_add_holes=True, package_pad_drill_size=[1, 1], package_pad_ddrill=0.5, style="flat", description="Crystal THT DS15 5.0mm length 1.5mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS15"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_DS15_d1.5mm_l5.0mm_Vertical", rm=1.7, pad_size=1, ddrill=0.5, pack_diameter=1.5, description="Crystal THT DS15 5.0mm length 1.5mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS15"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_Round_d1.5mm_Vertical", rm=1.7, pad_size=1, ddrill=0.5, pack_diameter=1.5, description="Crystal THT DS15 5.0mm length 1.5mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS15"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalAll(footprint_name="Crystal_DS10_d1.0mm_l4.3mm_Horizontal", rm=1.5, pad_size=1, ddrill=0.5, pack_width=4.3, pack_height=1, pack_rm=0.3, pack_offset=1.5, package_pad=True, package_pad_offset=2, package_pad_size=[4.3, 1.5], package_pad_add_holes=True, package_pad_drill_size=[1, 1], package_pad_ddrill=0.5, style="flat", description="Crystal THT DS10 4.3mm length 1.0mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS10"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_DS10_d1.0mm_l4.3mm_Vertical", rm=1.5, pad_size=1, ddrill=0.5, pack_diameter=1, description="Crystal THT DS10 4.3mm length 1.0mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS10"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalRoundVert(footprint_name="Crystal_Round_d1.0mm_Vertical", rm=1.5, pad_size=1, ddrill=0.5, pack_diameter=1, description="Crystal THT DS10 1.0mm diameter http://www.microcrystal.com/images/_Product-Documentation/03_TF_metal_Packages/01_Datasheet/DS-Series.pdf", tags=["DS10"], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54,1/2.54,1/2.54], rotate3d=[0, 0, 0]) makeCrystalAll(footprint_name="Crystal_HC49-U_Horizontal", rm=4.9, pad_size=1.5, ddrill=0.8, pack_width=13.0, pack_height=10.9, pack_rm=4.9, pack_offset=2, package_pad=True, package_pad_offset=2.5, package_pad_size=[13.5, 11], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-49/U http://5hertz.com/pdfs/04404_D.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=4.65, iheight3d=4) makeCrystalHC49Vert(footprint_name = "Crystal_HC49-U_Vertical", pins=2, rm=4.88, pad_size=1.5, ddrill=0.8, pack_width=10.9, pack_height=4.65, innerpack_width=10, innerpack_height=4, tags=standardtags+"HC-49/U", description="Crystal THT HC-49/U http://5hertz.com/pdfs/04404_D.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=13) makeCrystalHC49Vert(footprint_name="Crystal_HC49-U-3pin_Vertical", pins=3, rm=4.88, pad_size=1.5, ddrill=0.8, pack_width=10.9, pack_height=4.65, innerpack_width=10, innerpack_height=4, tags=standardtags+"HC-49/U", description="Crystal THT HC-49/U, 3pin-version, http://www.raltron.com/products/pdfspecs/crystal_hc_49_45_51.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc493p, height3d=13) makeCrystalHC49Vert(footprint_name = "Crystal_HC49-4H_Vertical", pins=2, rm=4.88, pad_size=1.5, ddrill=0.8, pack_width=11.05, pack_height=4.65, innerpack_width=10, innerpack_height=4, tags=standardtags+"HC-49-4H", description="Crystal THT HC-49-4H http://5hertz.com/pdfs/04404_D.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=4) makeCrystalAll(footprint_name="Crystal_HC18-U_Horizontal", rm=4.9, pad_size=1.5, ddrill=0.8, pack_width=13.0, pack_height=10.9, pack_rm=4.9, pack_offset=2, package_pad=True, package_pad_offset=2.5, package_pad_size=[13.5, 11], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-18/U http://5hertz.com/pdfs/04404_D.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=4.65, iheight3d=4) makeCrystalHC49Vert(footprint_name="Crystal_HC18-U_Vertical", pins=2, rm=4.9, pad_size=1.5, ddrill=0.8, pack_width=10.9, pack_height=4.65, innerpack_width=10, innerpack_height=4, tags=standardtags+"HC-18/U", description="Crystal THT HC-18/U, http://5hertz.com/pdfs/04404_D.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=13) makeCrystalAll(footprint_name="Crystal_HC33-U_Horizontal", rm=12.34, pad_size=2.7, ddrill=1.7, pack_width=19.7, pack_height=19.23, pack_rm=12.34, pack_offset=2.5, package_pad=True, package_pad_offset=2.5, package_pad_size=[20.5, 20], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-33/U http://pdi.bentech-taiwan.com/PDI/GEN20SPEV20HC3320U.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=8.94, iheight3d=8.05) makeCrystalHC49Vert(footprint_name="Crystal_HC33-U_Vertical", pins=2, rm=12.34, pad_size=2.7, ddrill=1.7, pack_width=19.23, pack_height=8.94, innerpack_width=18.42, innerpack_height=8.05, tags=standardtags+"HC-33/U", description="Crystal THT HC-33/U, http://pdi.bentech-taiwan.com/PDI/GEN20SPEV20HC3320U.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=19.7) makeCrystalAll(footprint_name="Crystal_HC50_Horizontal", rm=4.9, pad_size=2.3, ddrill=1.5, pack_width=13.36, pack_height=11.05, pack_rm=4.9, pack_offset=2.5, package_pad=True, package_pad_offset=2.5, package_pad_size=[14, 11.5], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-50 http://www.crovencrystals.com/croven_pdf/HC-50_Crystal_Holder_Rev_00.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=4.65, iheight3d=3.8) makeCrystalHC49Vert(footprint_name="Crystal_HC50_Vertical", pins=2, rm=4.9, pad_size=2.3, ddrill=1.5, pack_width=11.05, pack_height=4.65, innerpack_width=10.2, innerpack_height=3.8, tags=standardtags+"HC-50", description="Crystal THT HC-50, http://www.crovencrystals.com/croven_pdf/HC-50_Crystal_Holder_Rev_00.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=13.36) makeCrystalAll(footprint_name="Crystal_HC51_Horizontal", rm=12.35, pad_size=2.3, ddrill=1.2, pack_width=19.7, pack_height=19.3, pack_rm=12.35, pack_offset=2.5, package_pad=True, package_pad_offset=2.5, package_pad_size=[20.5, 20], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-51 http://www.crovencrystals.com/croven_pdf/HC-51_Crystal_Holder_Rev_00.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=8.9, iheight3d=7.6) makeCrystalHC49Vert(footprint_name="Crystal_HC51-U_Vertical", pins=2, rm=12.35, pad_size=2.3, ddrill=1.2, pack_width=19.3, pack_height=8.9, innerpack_width=18, innerpack_height=7.6, tags=standardtags+"HC-51/U", description="Crystal THT HC-51/U, http://www.crovencrystals.com/croven_pdf/HC-51_Crystal_Holder_Rev_00.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=19.7) makeCrystalAll(footprint_name="Crystal_HC52-U_Horizontal", rm=3.8, pad_size=1.5, ddrill=0.8, pack_width=8.8, pack_height=8, pack_rm=3.8, pack_offset=1.5, package_pad=True, package_pad_offset=1.5, package_pad_size=[9.5, 8.5], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-51/U http://www.kvg-gmbh.de/assets/uploads/files/product_pdfs/XS71xx.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=3.3, iheight3d=2.3) makeCrystalHC49Vert(footprint_name="Crystal_HC52-U_Vertical", pins=2, rm=3.8, pad_size=1.5, ddrill=0.8, pack_width=8, pack_height=3.3, innerpack_width=7, innerpack_height=2.3, tags=standardtags+"HC-52/U", description="Crystal THT HC-52/U, http://www.kvg-gmbh.de/assets/uploads/files/product_pdfs/XS71xx.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=8.8) makeCrystalHC49Vert(footprint_name="Crystal_HC52-U-3pin_Vertical", pins=3, rm=3.8, pad_size=1.5, ddrill=0.8, pack_width=8, pack_height=3.3, innerpack_width=7, innerpack_height=2.3, tags=standardtags+"HC-52/U", description="Crystal THT HC-52/U, http://www.kvg-gmbh.de/assets/uploads/files/product_pdfs/XS71xx.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc493p, height3d=8.8) makeCrystalAll(footprint_name="Crystal_HC52-8mm_Horizontal", rm=3.8, pad_size=1.5, ddrill=0.8, pack_width=8, pack_height=8, pack_rm=3.8, pack_offset=1.5, package_pad=True, package_pad_offset=1.5, package_pad_size=[8.5, 8.5], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-51/8mm http://www.kvg-gmbh.de/assets/uploads/files/product_pdfs/XS71xx.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=3.3, iheight3d=2.3) makeCrystalHC49Vert(footprint_name="Crystal_HC52-8mm_Vertical", pins=2, rm=3.8, pad_size=1.5, ddrill=0.8, pack_width=8, pack_height=3.3, innerpack_width=7, innerpack_height=2.3, tags=standardtags+"HC-49/U", description="Crystal THT HC-52/8mm, http://www.kvg-gmbh.de/assets/uploads/files/product_pdfs/XS71xx.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=8) makeCrystalAll(footprint_name="Crystal_HC52-6mm_Horizontal", rm=3.8, pad_size=1.5, ddrill=0.8, pack_width=6, pack_height=8, pack_rm=3.8, pack_offset=1.5, package_pad=True, package_pad_offset=1.5, package_pad_size=[6.5, 8.5], package_pad_add_holes=True, package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, style="hc49", description="Crystal THT HC-51/6mm http://www.kvg-gmbh.de/assets/uploads/files/product_pdfs/XS71xx.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49h, height3d=3.3, iheight3d=2.3) makeCrystalHC49Vert(footprint_name="Crystal_HC52-6mm_Vertical", pins=2, rm=3.8, pad_size=1.5, ddrill=0.8, pack_width=8, pack_height=3.3, innerpack_width=7, innerpack_height=2.3, tags=standardtags+"HC-49/U", description="Crystal THT HC-52/6mm, http://www.kvg-gmbh.de/assets/uploads/files/product_pdfs/XS71xx.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dhc49, height3d=6) makeCrystalHC49Vert(footprint_name="Resonator_Murata_DSN6", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=7, pack_height=2.54, innerpack_width=7, innerpack_height=2.54, tags=standardtagsres+" DSN6", description="Ceramic Resomator/Filter Murata DSN6, http://cdn-reichelt.de/documents/datenblatt/B400/DSN6NC51H.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=8) makeCrystalHC49Vert(footprint_name="Resonator_Murata_DSS6", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=7, pack_height=2.54, innerpack_width=7, innerpack_height=2.54, tags=standardtagsres + " DSS6", description="Ceramic Resomator/Filter Murata DSS6, http://cdn-reichelt.de/documents/datenblatt/B400/DSN6NC51H.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=7) makeCrystalHC49Vert(footprint_name="Resonator_Murata_CSTLSxxxG", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=8, pack_height=3, innerpack_width=8, innerpack_height=3, tags=standardtagsres + " CSTLSxxxG", description="Ceramic Resomator/Filter Murata CSTLSxxxG, http://www.murata.com/~/media/webrenewal/support/library/catalog/products/timingdevice/ceralock/p17e.ashx", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=5.5) makeCrystalHC49Vert(footprint_name="Resonator_Murata_CSTLSxxxX", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=5.5, pack_height=3, innerpack_width=5.5, innerpack_height=3, tags=standardtagsres + " CSTLSxxxX", description="Ceramic Resomator/Filter Murata CSTLSxxxX, http://www.murata.com/~/media/webrenewal/support/library/catalog/products/timingdevice/ceralock/p17e.ashx", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=5.5) makeCrystalHC49Vert(footprint_name="Resonator", pins=2, addSizeFootprintName=True, rm=5, pad_size=1.5, ddrill=0.8, pack_width=10, pack_height=5, innerpack_width=10, innerpack_height=5, tags=standardtagsres + "", description="Ceramic Resomator/Filter 10.0x5.0 RedFrequency MG/MT/MX series, http://www.red-frequency.com/download/datenblatt/redfrequency-datenblatt-ir-zta.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate3d=[0, 0, 0], script3d=script3dres2, height3d=10) makeCrystalHC49Vert(footprint_name="Resonator", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.5, ddrill=0.8, pack_width=10, pack_height=5, innerpack_width=10, innerpack_height=5, tags=standardtagsres + "", description="Ceramic Resomator/Filter 10.0x5.0mm^2 RedFrequency MG/MT/MX series, http://www.red-frequency.com/download/datenblatt/redfrequency-datenblatt-ir-zta.pdf", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=10) makeCrystalHC49Vert(footprint_name="Resonator", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=7, pack_height=2.5, innerpack_width=7, innerpack_height=2.5, tags=standardtagsres + "", description="Ceramic Resomator/Filter 7.0x2.5mm^2", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=5.5) makeCrystalHC49Vert(footprint_name="Resonator", pins=2, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=7, pack_height=2.5, innerpack_width=7, innerpack_height=2.5, tags=standardtagsres + "", description="Ceramic Resomator/Filter 7.0x2.5mm^2", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dres2, height3d=5.5) makeCrystalHC49Vert(footprint_name="Resonator", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=8, pack_height=3.5, innerpack_width=8, innerpack_height=3.5, tags=standardtagsres + "", description="Ceramic Resomator/Filter 8.0x3.5mm^2", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=6.5) makeCrystalHC49Vert(footprint_name="Resonator", pins=2, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=8, pack_height=3.5, innerpack_width=8, innerpack_height=3.5, tags=standardtagsres + "", description="Ceramic Resomator/Filter 8.0x3.5mm^2", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dres2, height3d=6.5) makeCrystalHC49Vert(footprint_name="Resonator", pins=3, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=6, pack_height=3.0, innerpack_width=6, innerpack_height=3.0, tags=standardtagsres + "", description="Ceramic Resomator/Filter 6.0x3.0mm^2", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dres3, height3d=6.5) makeCrystalHC49Vert(footprint_name="Resonator", pins=2, addSizeFootprintName=True, rm=5, pad_size=1.7, ddrill=1, pack_width=6, pack_height=3.0, innerpack_width=6, innerpack_height=3.0, tags=standardtagsres + "", description="Ceramic Resomator/Filter 6.0x3.0mm^2", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1/2.54, 1/2.54, 1/2.54], rotate3d=[0, 0, 0], script3d=script3dres2, height3d=6.5) ================================================ FILE: scripts/Diodes_SMD/generator found under SMD_chip_package_rlc-etc ================================================ ================================================ FILE: scripts/Diodes_THT/make_Diodes_THT.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_resistorlike import * if __name__ == '__main__': # standard resistors: http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf type = "cyl" script3d="d_hor.py" with open(script3d, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dv="d_ver.py" with open(script3dv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dvkup="d_ver_kup.py" with open(script3dvkup, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dglass="d_hor_glass.py" with open(script3dglass, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dvglass="d_ver_glass.py" with open(script3dvglass, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dvkupglass="d_ver_kup_glass.py" with open(script3dvkupglass, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") d2=0 R_POW = 0 clname="D" lbname="${KISYS3DMOD}/Diode_THT" deco="diode" deco_kup="diode_KUP" seriesname = "DO-27"; w=9.52; d=5.33; ddrill=1.2; add_description=", http://www.slottechforum.com/slotinfo/Techstuff/CD2%20Diodes%20and%20Transistors/Cases/Diode%20DO-27.jpg"; name_additions=[] for rm in [12.7, 15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "DO-41_SOD81"; w=5.2; d=2.7; ddrill=1.1; add_description=", https://www.diodes.com/assets/Package-Files/DO-41-Plastic.pdf"; name_additions=[] for rm in [7.62, 10.16, 12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [2.54, 3.81, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "DO-34_SOD68"; w=3.04; d=1.6; ddrill=0.75; add_description=", https://www.nxp.com/docs/en/data-sheet/KTY83_SER.pdf"; name_additions=[] for rm in [7.62, 10.16, 12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [2.54, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "DO-35_SOD27"; w=4; d=2; ddrill=0.8; add_description=", http://www.diodes.com/_files/packages/DO-35.pdf"; name_additions=[] for rm in [7.62, 10.16, 12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dglass) for rm in [2.54, 3.81, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkupglass) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvglass) seriesname = "A-405"; w=5.2; d=2.7; ddrill=0.9; add_description=", http://www.diodes.com/_files/packages/A-405.pdf"; name_additions=[] for rm in [7.62, 10.16, 12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [2.54, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "DO-15"; w=7.6; d=3.6; ddrill=1.2; add_description=", http://www.diodes.com/_files/packages/DO-15.pdf"; name_additions=[] for rm in [10.16, 12.7, 15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [2.54, 3.81, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "DO-201"; w=9.53; d=5.21; ddrill=1.3; add_description=", http://www.diodes.com/_files/packages/DO-201.pdf"; name_additions=[] for rm in [12.7, 15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [3.81, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "DO-201AD"; w=9.5; d=5.2; ddrill=1.6; add_description=", http://www.diodes.com/_files/packages/DO-201AD.pdf"; name_additions=[] for rm in [12.7, 15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [3.81, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "DO-201AE"; w=9; d=5.3; ddrill=1.3; add_description=", http://www.farnell.com/datasheets/529758.pdf"; name_additions=[] for rm in [12.7, 15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [3.81, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "P600_R-6"; w=9.1; d=9.1; ddrill=1.6; add_description=", http://www.vishay.com/docs/88692/p600a.pdf, http://www.diodes.com/_files/packages/R-6.pdf"; name_additions=[] for rm in [12.7,20]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "5W"; w=8.9; d=3.7; ddrill=1.4; add_description=", http://www.diodes.com/_files/packages/8686949.gif"; name_additions=[] for rm in [10.16, 12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "5KP"; w=7.62; d=9.53; ddrill=1.4; add_description=", http://www.diodes.com/_files/packages/8686949.gif"; name_additions=[] for rm in [10.16, 12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "5KPW"; w=9; d=8; ddrill=1.6; add_description=", http://www.diodes.com/_files/packages/8686949.gif"; name_additions=[] for rm in [12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3d) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkup) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dv) seriesname = "T-1"; w=3.2; d=2.6; ddrill=1; add_description=", http://www.diodes.com/_files/packages/T-1.pdf"; name_additions=[] for rm in [5.08, 10.16, 12.7]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dglass) for rm in [2.54]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco_kup, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvkupglass) makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, deco=deco, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, classname=clname, lib_name=lbname, specialtags=[],script3d=script3dvglass) ================================================ FILE: scripts/Fuse/ptc-fuse-tht.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) sys.path.append(os.path.join(sys.path[0], "..", "tools")) from KicadModTree import * from drawing_tools import * def ptc_fuse_tht(args): footprint_name = args["name"] datasheet = args["datasheet"] ihold = args["ihold"] itrip = args["itrip"] drill = args["drill"] w = args["width"] h = args["height"] pitch = args["pitch"] offset = args["offset"] f = Footprint(footprint_name) f.setDescription("PTC Resettable Fuse, Ihold = " + ihold + ", Itrip=" + itrip + ", " + datasheet) f.setTags("ptc resettable fuse polyfuse THT") f.append(Model(filename="${KISYS3DMOD}/Fuse.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) d = [drill, drill] p = [drill + 1.0, drill + 1.0] s = [1.0, 1.0] t = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 silk = 0.1 crtYd = 0.25 clearance = 0.3 xPin1 = 0.0 xPin2 = pitch xCenter = pitch / 2 xLeft = xCenter - w / 2 xRight = xCenter + w / 2 xLeftSilk = xLeft - silk xRightSilk = xRight + silk xLeftCrtYd = xLeft - crtYd xRightCrtYd = xRight + crtYd yPin1 = 0.0 yPin2 = offset yCenter = offset / 2 yTop = yCenter - h / 2 yBottom = yCenter + h / 2 yRef = yTop - 1.0 yValue = yBottom + 1.0 yTopSilk = yTop - silk yBottomSilk = yBottom + silk yTopCrtYd = yTop - crtYd yBottomCrtYd = yBottom + crtYd keepout = [] ko_diameter = p[0] + 2 * clearance # Pads pin = 1 for coord in [[xPin1, yPin1], [xPin2, yPin2]]: f.append(Pad(number=str(pin), type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=coord, size=p, layers=Pad.LAYERS_THT, drill=d)) keepout = keepout + addKeepoutRound(coord[0], coord[1], ko_diameter, ko_diameter) pin = pin + 1 # Text f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s, thickness=t)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s, thickness=t)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=s, thickness=t)) # Fab outline f.append(RectLine(start=[xLeft, yTop], end=[xRight, yBottom], layer="F.Fab", width=wFab)) # Silk outline addRectWithKeepout(f, xLeftSilk, yTopSilk, xRightSilk - xLeftSilk, yBottomSilk - yTopSilk, "F.SilkS", wSilkS, keepout) # Courtyard f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(ptc_fuse_tht) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("datasheet", type=str, required=False, default="http://www.bourns.com/docs/Product-Datasheets/mfrg.pdf") parser.add_parameter("ihold", type=str, required=True) parser.add_parameter("itrip", type=str, required=True) parser.add_parameter("drill", type=float, required=False, default=1.01) parser.add_parameter("pitch", type=float, required=False, default=5.1) parser.add_parameter("height", type=float, required=False, default=3.0) parser.add_parameter("width", type=float, required=True) parser.add_parameter("offset", type=float, required=False, default=1.2) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Fuse/ptc-fuse-tht.yaml ================================================ Fuse_Bourns_MF-RG300: ihold: 3.0A itrip: 5.1A width: 7.1 Fuse_Bourns_MF-RG400: ihold: 4.0A itrip: 6.8A width: 9.9 Fuse_Bourns_MF-RG500: ihold: 5.0A itrip: 8.5A width: 10.4 Fuse_Bourns_MF-RG600: ihold: 6.0A itrip: 10.2A width: 10.7 Fuse_Bourns_MF-RG650: ihold: 6.5A itrip: 11.1A width: 11.2 Fuse_Bourns_MF-RG700: ihold: 7.0A itrip: 11.9A width: 11.2 Fuse_Bourns_MF-RG800: ihold: 8.0A itrip: 13.6A width: 12.7 Fuse_Bourns_MF-RG900: ihold: 9.0A itrip: 15.3A width: 14.0 Fuse_Bourns_MF-RG1000: ihold: 10.0A itrip: 17.0A width: 16.5 Fuse_Bourns_MF-RG1100: ihold: 11.0A itrip: 18.7A width: 17.5 Fuse_Bourns_MF-RHT050: ihold: 0.5A itrip: 0.92A width: 7.4 drill: 0.71 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT070: ihold: 0.7A itrip: 1.4A width: 6.86 drill: 0.71 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT100: ihold: 1.0A itrip: 1.8A width: 9.7 drill: 0.71 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT200: ihold: 2.0A itrip: 3.8A width: 9.4 drill: 0.71 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT300: ihold: 3.0A itrip: 6.0A width: 8.8 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT400: ihold: 4.0A itrip: 7.5A width: 10.0 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT500: ihold: 5.0A itrip: 9.0A width: 11.2 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT550: ihold: 5.5A itrip: 10.0A width: 11.2 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT600: ihold: 6.0A itrip: 10.8A width: 11.2 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT650: ihold: 6.5A itrip: 12.0A width: 12.7 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT700: ihold: 7.0A itrip: 13.0A width: 14.0 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT750: ihold: 7.5A itrip: 13.1A width: 14.0 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT800: ihold: 8.0A itrip: 15.0A width: 16.5 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT900: ihold: 9.0A itrip: 16.5A width: 16.5 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT1000: ihold: 10.0A itrip: 18.5A width: 17.5 pitch: 10.2 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT1100: ihold: 11.0A itrip: 20.0A width: 21.0 pitch: 10.2 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf Fuse_Bourns_MF-RHT1300: ihold: 13.0A itrip: 24.0A width: 23.5 height: 3.6 pitch: 10.2 drill: 1.2 datasheet: http://www.bourns.com/docs/product-datasheets/mfrht.pdf ================================================ FILE: scripts/Inductor_SMD/Inductor_SMD.py ================================================ #!/usr/bin/env python3 import sys import os import re # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) # load scripts sys.path.append(os.path.join(sys.path[0], "..")) from KicadModTree import * from general.StandardBox import * def qfn(args): extraffablines = [] footprint_name = args["name"] description = args["description"] datasheet = args["datasheet"] fptag = args["tags"] SmdTht = args["smd_tht"] at = args["at"] size = args["size"] pins = args["pins"] extratexts = args["extratexts"] dir3D = 'Inductor_SMD.3dshapes' f = Footprint(footprint_name) file3Dname = "${KISYS3DMOD}/" + dir3D + "/" + footprint_name + ".wrl" words = footprint_name.split("_") if words[-1].lower().startswith('handsolder'): words[-1] = '' ff = '_'.join(words) file3Dname = "${KISYS3DMOD}/" + dir3D + "/" + ff + ".wrl" f.append(StandardBox(footprint=f, description=description, datasheet=datasheet, at=at, size=size, tags=fptag, SmdTht=SmdTht, extratexts=extratexts, pins=pins, file3Dname=file3Dname )) # # # file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(qfn) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("description", type=str, required=True) parser.add_parameter("datasheet", type=str, required=True) parser.add_parameter("tags", type=str, required=True) parser.add_parameter("smd_tht", type=str, required=False, default='tht') parser.add_parameter("at", type=list, required=True) parser.add_parameter("size", type=list, required=False) parser.add_parameter("pins", type=list, required=True) parser.add_parameter("extratexts", type=list, required=False) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Inductor_SMD/Inductor_SMD.yml ================================================ # # extratexts: must be included even if the string is empty, it is a quirk in ModArgparser.py # # size: is normally 2 dimensional, creaing a box, in this case 6x6 mm # size: [6.00, 6.00] # # But it is possible to define how the corners should look like with following optional paramters # # ULR : Upper left corner with arc # ULP: Upper left corner with rectangular cut # # URR : Upper right corner with arc # URP: Upper right corner with rectangular cut # # LRR : Lower right corner with arc # LRP: Lower right corner with rectangular cut # # LLR : Lower left corner with arc # LLP: Lower left corner with rectangular cut # # # size: [6.00, 6.00, ['ULP', 0.9, 0.9]] # means a box of 6x6 mm but upper left corner is cut 0.9 mm both in x and y led # # size: [6.00, 6.00, ['ULR', 0.2], ['LRP', 0.9, 0.9]] # means a box of 6x6 mm but upper left corner is cut by an arc with radius 0.2 # and lower right corner is cut 0.9 in both x and y led # # L_TDK_SLF6025: description: "Inductor, TDK, SLF6025, 6.0mmx6.0mm" datasheet: "https://product.tdk.com/info/en/document/catalog/smd/inductor_commercial_power_slf6025_en.pdf" tags: "Inductor TDK_SLF6025" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-3.00, 3.00] size: [6.00, 6.00] # size: [6.00, 6.00] smd_tht: "smd" pins: [["smd", "1", -2.75, 0, 1.5, 2.2, 0.0], ["smd", "2", 2.75, 0, 1.5, 2.2, 0.0]] L_TDK_SLF6028: description: "Inductor, TDK, SLF6028, 6.0mmx6.0mm" datasheet: "https://product.tdk.com/info/en/document/catalog/smd/inductor_commercial_power_slf6028_en.pdf" tags: "Inductor TDK_SLF6028" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-3.00, 3.00] size: [6.00, 6.00] smd_tht: "smd" pins: [["smd", "1", -2.75, 0, 1.5, 2.2, 0.0], ["smd", "2", 2.75, 0, 1.5, 2.2, 0.0]] L_TDK_SLF6045: description: "Inductor, TDK, SLF6045, 6.0mmx6.0mm" datasheet: "https://product.tdk.com/info/en/document/catalog/smd/inductor_commercial_power_slf6045_en.pdf" tags: "Inductor TDK_SLF6045" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-3.00, 3.00] size: [6.00, 6.00] smd_tht: "smd" pins: [["smd", "1", -2.75, 0, 1.5, 2.2, 0.0], ["smd", "2", 2.75, 0, 1.5, 2.2, 0.0]] L_TDK_SLF7032: description: "Inductor, TDK, SLF7032, 7.0mmx7.0mm" datasheet: "https://product.tdk.com/info/en/document/catalog/smd/inductor_commercial_power_slf7032_en.pdf" tags: "Inductor TDK_SLF7032" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-3.5, 3.5] size: [7.00, 7.00] smd_tht: "smd" pins: [["smd", "1", -3.15, 0, 1.5, 2.2, 0.0], ["smd", "2", 3.15, 0, 1.5, 2.2, 0.0]] L_TDK_SLF7045: description: "Inductor, TDK, SLF7045, 7.0mmx7.0mm" datasheet: "https://product.tdk.com/info/en/document/catalog/smd/inductor_commercial_power_slf7045_en.pdf" tags: "Inductor TDK_SLF7045" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-3.5, 3.5] size: [7.00, 7.00] smd_tht: "smd" pins: [["smd", "1", -3.15, 0, 1.5, 2.2, 0.0], ["smd", "2", 3.15, 0, 1.5, 2.2, 0.0]] L_TDK_SLF7055: description: "Inductor, TDK, SLF7055, 7.0mmx7.0mm" datasheet: "https://product.tdk.com/info/en/document/catalog/smd/inductor_commercial_power_slf7055_en.pdf" tags: "Inductor TDK_SLF7055" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-3.5, 3.5] size: [7.00, 7.00] smd_tht: "smd" pins: [["smd", "1", -3.15, 0, 1.5, 2.2, 0.0], ["smd", "2", 3.15, 0, 1.5, 2.2, 0.0]] L_TDK_SLF10145: description: "Inductor, TDK, SLF10145, 10.1mmx10.1mm" datasheet: "https://product.tdk.com/info/en/catalog/datasheets/inductor_automotive_power_slf10145-h_en.pdf" tags: "Inductor TDK_SLF10145" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-5.05, 5.05] size: [10.1, 10.1] smd_tht: "smd" pins: [["smd", "1", -4.05, 0, 2.5, 3.2, 0.0], ["smd", "2", 4.05, 0, 2.5, 3.2, 0.0]] L_TDK_SLF10165: description: "Inductor, TDK, SLF10165, 10.1mmx10.1mm" datasheet: "https://product.tdk.com/info/en/catalog/datasheets/inductor_commercial_power_slf10165_en.pdf" tags: "Inductor TDK_SLF10165" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-5.05, 5.05] size: [10.1, 10.1] smd_tht: "smd" pins: [["smd", "1", -4.05, 0, 2.5, 3.2, 0.0], ["smd", "2", 4.05, 0, 2.5, 3.2, 0.0]] L_TDK_SLF12555: description: "Inductor, TDK, SLF12555, 12.5mmx12.5mm" datasheet: "https://product.tdk.com/info/en/catalog/datasheets/inductor_commercial_power_slf12555_en.pdf" tags: "Inductor SLF12555" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-6.25, 6.25] size: [12.5, 12.5] smd_tht: "smd" pins: [["smd", "1", -5.55, 0, 2.6, 3.2, 0.0], ["smd", "2", 5.55, 0, 2.6, 3.2, 0.0]] L_TDK_SLF12565: description: "Inductor, TDK, SLF12565, 12.5mmx12.5mm" datasheet: "https://product.tdk.com/info/en/catalog/datasheets/inductor_automotive_power_slf12565-h_en.pdf" tags: "Inductor SLF12565" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-6.25, 6.25] size: [12.5, 12.5] smd_tht: "smd" pins: [["smd", "1", -5.55, 0, 2.6, 3.2, 0.0], ["smd", "2", 5.55, 0, 2.6, 3.2, 0.0]] L_TDK_SLF12575: description: "Inductor, TDK, SLF12575, 12.5mmx12.5mm" datasheet: "https://product.tdk.com/info/en/catalog/datasheets/inductor_automotive_power_slf12575-h_en.pdf" tags: "Inductor SLF12575" extratexts: [[-49.0, -0.05, "", "F.SilkS", 3.0, 3.0]] at: [-6.25, 6.25] size: [12.5, 12.5] smd_tht: "smd" pins: [["smd", "1", -5.55, 0, 2.6, 3.2, 0.0], ["smd", "2", 5.55, 0, 2.6, 3.2, 0.0]] ================================================ FILE: scripts/Inductors/Choke_Schaffner_RNXXX.py ================================================ #http://katalog.we-online.com/en/pbs/WE-MAPI] #sizes,shapes,etc] #name, Type, #pins, A, B, H, L, W, , P, PDiam, PadSize inductors = [ ["RN102", 0, 4, 10.0, 10.0, 9.0, 14.0, 14.0, 4.0, 0.6, 2.0 ], ["RN112", 1, 4, 15.0, 10.0, 12.6, 17.7, 17.1, 4.0, 0.8, 2.0 ], ["RN114", 1, 4, 20.1, 12.5, 13.2, 22.5, 21.5, 4.0, 0.8, 2.0 ], ["RN116", 1, 4, 20.1, 12.5, 13.2, 22.5, 21.5, 4.0, 0.8, 2.0 ], ["RN122", 1, 4, 25.0, 15.0, 16.5, 28.0, 27.0, 4.0, 0.8, 2.0 ], ["RN142", 1, 4, 30.0, 20.0, 19.7, 33.1, 32.5, 4.3, 0.8, 2.0 ], ["RN143", 1, 4, 30.0, 20.0, 19.7, 33.1, 32.5, 4.3, 0.8, 2.0 ], ["RN152", 2, 4, 40.0, 15.0, 25.0, 43.0, 41.8, 4.5, 1.2, 2.5 ], ["RN202", 3, 4, 5.1, 15.2, 13.5, 8.8, 18.2, 4.5, 0.8, 2.0 ], ["RN204", 3, 4, 7.6, 10.0, 14.3, 9.0, 14.0, 4.0, 0.5, 2.0 ], ["RN212", 3, 4, 10.0, 15.0, 20.0, 12.5, 18.0, 4.0, 0.8, 2.0 ], ["RN214", 3, 4, 12.5, 10.0, 25.0, 15.5, 23.0, 4.0, 0.8, 2.0 ], ["RN216", 3, 4, 12.5, 10.0, 25.0, 15.5, 23.0, 4.0, 0.8, 2.0 ], ["RN218", 3, 4, 10.0, 12.5, 20.0, 12.5, 18.0, 4.0, 0.8, 2.0 ], ["RN222", 3, 4, 15.0, 12.5, 29.3, 18.0, 31.0, 4.0, 0.8, 2.0 ], ["RN232", 3, 4, 15.0, 12.5, 34.3, 18.0, 31.0, 4.2, 0.8, 2.0 ], ["RN242", 3, 4, 15.0, 12.5, 34.3, 18.0, 31.0, 4.2, 0.8, 2.0 ] ] import sys import os import math output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append(os.path.join(sys.path[0], "..", "..")) from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray prefix = "Choke_Schaffner_" part = "{serie}-0{pn}" dims = "{l:0.1f}mmx{w:0.1f}mm" dims2 = "{l:0.1f}x{w:0.1f}mm" desc = "Current-compensated Chokes, Schaffner, {pn}" tags = "chokes schaffner tht" TargetDir = "Inductor_THT.3dshapes" Datasheet = "https://www.schaffner.com/products/download/product/datasheet/rn-series-common-mode-chokes-new/" for inductor in inductors: Serie,Type,PN,A,B,H,L,W,P,PDiam,PadSize=inductor Pin1x1 = 0 Pin1y1 = 0 Pin1dx = 1.0 RefX1 = 0 RefY1 = round((0 - ((W - B) / 2) - 1.5), 2) cx = round(A / 2, 2) cy = round(B / 2, 2) fp_name = prefix + part.format(serie=str(Serie), pn=str(PN)) + "-" + dims2.format(l=L,w=W) fp = Footprint(fp_name) description = desc.format(pn = part.format(serie=str(Serie), pn=str(PN))) + ", " + dims.format(l=L,w=W) + " " + Datasheet # fp.append(Line(start=[cx - (L / 2), cy - (W / 2)], end=[cx + (L / 2), cy - (W / 2)],layer='F.Fab', width=0.01)) # fp.append(Line(start=[cx + (L / 2), cy - (W / 2)], end=[cx + (L / 2), cy + (W / 2)],layer='F.Fab', width=0.01)) # fp.append(Line(start=[cx + (L / 2), cy + (W / 2)], end=[cx - (L / 2), cy + (W / 2)],layer='F.Fab', width=0.01)) # fp.append(Line(start=[cx - (L / 2), cy + (W / 2)], end=[cx - (L / 2), cy - (W / 2)],layer='F.Fab', width=0.01)) if Type == 0: # # This have the shape of a box with rounded corners # # # Add the component outline # # Top line Layer = ['F.Fab', 'F.SilkS', 'F.CrtYd'] LayerW = [0.1, 0.12, 0.05] LayerD = [0, 0.12, 0.25] for i in range(0, 3): myLayer = Layer[i] myLayerW = LayerW[i] myLayerD = LayerD[i] # # Top line x1 = 0 y1 = 0 - (((W - B) / 2) + myLayerD) x2 = A y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # Top right arc fp.append(Arc(center=[round(A, 2), round(0, 2)], start=[round(x2, 2), round(y2, 2)], angle=90.0, layer=myLayer, width=myLayerW)) # Right line x1 = A + ((L - A) / 2) + myLayerD y1 = 0 x2 = x1 y2 = B fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # Bottom right arc fp.append(Arc(center=[round(A, 2), round(B, 2)], start=[round(x2, 2), round(y2, 2)], angle=90.0, layer=myLayer, width=myLayerW)) # Bottom line x1 = A y1 = B + ((W - B) / 2) + myLayerD x2 = 0 y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # Bottom left arc fp.append(Arc(center=[round(0, 2), round(B, 2)], start=[round(x2, 2), round(y2, 2)], angle=90.0, layer=myLayer, width=myLayerW)) # Left line if (i == 0): x1 = 0 - (((L - A) / 2) + myLayerD) y1 = B x2 = x1 y2 = 2 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) x1 = x2; y1 = y2 x2 = x1 + 1 y2 = 1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) x1 = x2; y1 = y2 x2 = x1 - 1 y2 = 0 else: x1 = 0 - (((L - A) / 2) + myLayerD) y1 = B x2 = x1 y2 = 0 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # Top left arc fp.append(Arc(center=[round(0, 2), round(0, 2)], start=[round(x2, 2), round(y2, 2)], angle=90.0, layer=myLayer, width=myLayerW)) Pin1x1 = 0 - (((L - A) / 2) + 0.25) Pin1y1 = 0 - (((W - B) / 2) + 0.25) Pin1dx = 3.0 elif Type == 1: # # This have the shape of a box with rounded top and bottom side # # # Add the component outline # # Calculate the arc # Points = [] Layer = ['F.Fab', 'F.SilkS', 'F.CrtYd'] LayerW = [0.1, 0.12, 0.05] LayerD = [0, 0.12, 0.25] # k = 0.0 m = 0.0 dx = round(L / 3, 2) dy = round(((W - B) / 2), 2) for i in range(0, 3): myLayer = Layer[i] myLayerW = LayerW[i] myLayerD = LayerD[i] # if (i == 0): # # Top arc # Fabh = dy angleD = 30.0 Fabalpha = math.radians(angleD) x1 = round(cx, 2) y1 = round(0, 2) tdy = Fabh * math.cos(Fabalpha) tdx = Fabh * math.sin(Fabalpha) x2 = round(x1 - tdx, 2) y2 = round(0 - tdy, 2) p1 = [x1, y1, x2, y2] Points.append(p1) fp.append(Arc(center=[x1, y1], start=[x2, y2], angle=2*angleD, layer=myLayer, width=myLayerW)) # # Top left line # x1 = round(cx - (L / 2), 2) y1 = round(0 - (PadSize / 2), 2) stx1 = x1 sty1 = y1 x2 = x2 y2 = y2 p1 = [x1, y1, x2, y2] Points.append(p1) fp.append(Line(start=[x1, y1],end=[x2, y2], layer=myLayer, width=myLayerW)) # # Top right line # x1 = round(cx + tdx, 2) y1 = y2 x2 = round(cx + (L / 2), 2) y2 = round(0 - (PadSize / 2), 2) p1 = [x1, y1, x2, y2] Points.append(p1) fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # # Right line # x1 = x2 y1 = y2 x2 = x1 y2 = round(B + (PadSize / 2), 2) tty4 = y2; p1 = [x1, y1, x2, y2] Points.append(p1) fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # # # Bottom arc # Fabh = dy angleD = 30.0 Fabalpha = math.radians(angleD) x1 = round(cx, 2) y1 = round(B, 2) tdy = Fabh * math.cos(Fabalpha) tdx = Fabh * math.sin(Fabalpha) x3 = round(cx + tdx, 2) y3 = round(B + tdy, 2) p1 = [x1, y1, x3, y3] Points.append(p1) fp.append(Arc(center=[x1, y1], start=[x3, y3], angle=2*angleD, layer=myLayer, width=myLayerW)) # # Bottom right line # x1 = x2 y1 = y2 x2 = x3 y2 = y3 p1 = [x1, y1, x2, y2] Points.append(p1) fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # x1 = round(cx - tdx, 2) y1 = y3 x2 = round(cx - (L / 2), 2) y2 = tty4 p1 = [x1, y1, x2, y2] Points.append(p1) fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # # Left line including pin 1 chamfer # x1 = x2 y1 = y2 x2 = x1 y2 = sty1 p1 = [x1, y1, x2, y2] Points.append(p1) y2 = 0.5 fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # x1 = x2 y1 = y2 x2 = x2 + 0.5 y2 = 0; fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # x1 = x2 y1 = y2 x2 = x2 - 0.5 y2 = -0.5; fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # x1 = x2 y1 = y2 x2 = x2 y2 = sty1 fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # Fabx1 = x2; Faby1 = y2; else: # # Y delta # point = Points[1] k = (point[3] - point[1]) / (point[2] - point[0]) m = (point[1] - k * point[0]) - myLayerD - 0.02 x1 = point[0] - myLayerD y1 = k * x1 + m ddy = math.fabs(math.sqrt(math.pow(point[1], 2)) - math.sqrt(math.pow(y1, 2))) # Top arc point = Points[0] Fabh = dy x1 = point[0] cx1 = x1 y1 = round(point[1] - myLayerD, 2) tdy = Fabh * math.cos(Fabalpha) tdx = Fabh * math.sin(Fabalpha) x2 = round(point[2], 2) cx2 = x2 y2 = round(point[3] - myLayerD - 0.02, 2) fp.append(Arc(center=[x1, y1], start=[x2, y2], angle=2*angleD, layer=myLayer, width=myLayerW)) # # Top left line # point = Points[1] x1 = round(point[0] - myLayerD, 2) stx1 = x1 y1 = round(k * x1 + m, 2) sty1 = y1 x2 = round(point[2], 2) y2 = round((k * x2 + m), 2) fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # Top right line point = Points[2] x1 = round(cx1 + (cx1 - cx2), 2) y1 = y2 x2 = round(point[2] + myLayerD, 2) y2 = sty1 fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # # Right line # point = Points[3] x1 = x2 y1 = y2 x2 = x1 tx2 = x2 y2 = round(point[3] + ddy, 2) ty2 = y2 fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # # Bottom arc # point = Points[4] Fabh = dy x1 = point[0] cx1 = x1 y1 = round(point[1] + myLayerD, 2) tdy = Fabh * math.cos(Fabalpha) tdx = Fabh * math.sin(Fabalpha) x3 = round(point[2], 2) y3 = round(point[3] + myLayerD + 0.02, 2) fp.append(Arc(center=[x1, y1], start=[x3, y3], angle=2*angleD, layer=myLayer, width=myLayerW)) # # Bottom right line # point = Points[5] x1 = tx2 y1 = ty2 x2 = x3 y2 = y3 fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # Bottom left line point = Points[6] x1 = round(cx1 - tdx, 2) y1 = y3 x2 = stx1 y2 = ty2 fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) # point = Points[7] x1 = x2 y1 = y2 x2 = x1 y2 = sty1 fp.append(Line(start=[x1, y1], end=[x2, y2], layer=myLayer, width=myLayerW)) Pin1x1 = x2 Pin1y1 = y2 Pin1dx = 0.25 RefX1 = 1.0 RefY1 = -5 elif Type == 2: # # This have the shape of a hexagon # Points = [] # Add the component outline # ty = ((W - B) / 2) alpha = 30.0 # 70 degree alphar = ((2 * math.pi) / 360.0) * alpha tx = ty * (math.sin(alphar) / math.cos(alphar)) x1 = 0 - ((L - A) / 2) y1 = 0 x2 = x1 + tx y2 = y1 - ty k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 + (L - (2 * tx)) y2 = y1 k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 + tx y2 = y1 + ty k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 y2 = y1 + B k = 0 m = 0 p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 - tx y2 = y1 + ty k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 - (L - (2 * tx)) y2 = y1 k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 - tx y2 = y1 - ty k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = 0 - ((L - A) / 2) tx2 = x2 y2 = 2 k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x2 + 1 y2 = 1 k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = tx2 y2 = 0 k = (y1 - y2) / (x1 - x2) m = y1 - (k * x1) p1 = [x1, y1, x2, y2, k, m] Points.append(p1) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) # # Add the component outline # PadDistance = 0.75 space=0.12 p1 = Points[0] k = p1[4] m = p1[5] y1 = (0 - ((PadSize / 2) + PadDistance)) x1 = ((y1 - m) / k) y1 = y1 - (space * math.sin(alphar)) x1 = x1 - (space * math.cos(alphar)) y2 = p1[3] - space x2 = ((y2 - (m - (2 * space))) / k) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # # Top line # p1 = Points[1] x1 = x2 y1 = y2 x2 = p1[2] + (space * math.sin(alphar)) y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # p1 = Points[2] k = p1[4] m = p1[5] x1 = x2 y1 = y2 y2 = (0 - ((PadSize / 2) + PadDistance)) x2 = ((y2 - m) / k) y2 = y2 - (space * math.sin(alphar)) x2 = x2 + (space * math.cos(alphar)) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # # right side line # p1 = Points[3] k = p1[4] m = p1[5] x1 = p1[0] + space y1 = ((PadSize / 2) + PadDistance) x2 = x1 y2 = B - ((PadSize / 2) + 0.5) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # p1 = Points[4] k = p1[4] m = p1[5] y1 = B + ((PadSize / 2) + PadDistance) x1 = ((y1 - m) / k) y1 = y1 + (space * math.sin(alphar)) x1 = x1 + (space * math.cos(alphar)) y2 = p1[3] + space x2 = ((y2 - (m + (2 * space))) / k) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # # Bottom line # p1 = Points[5] x1 = x2 y1 = y2 x2 = p1[2] - (space * math.sin(alphar)) y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # p1 = Points[6] k = p1[4] m = p1[5] x1 = x2 y1 = y2 y2 = B + ((PadSize / 2) + PadDistance) x2 = ((y2 - m) / k) y2 = y2 + (space * math.sin(alphar)) x2 = x2 - (space * math.cos(alphar)) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # # Left side line # p1 = Points[7] k = p1[4] m = p1[5] x1 = p1[0] - space y1 = B - ((PadSize / 2) + PadDistance) x2 = x1 y2 = ((PadSize / 2) + PadDistance) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # # Add the component courtyard # PadDistance = 0.75 space=0.25 p1 = Points[0] k = p1[4] m = p1[5] y1 = (0 - ((PadSize / 2) + PadDistance)) x1 = ((y1 - m) / k) y1 = y1 - (space * math.sin(alphar)) x1 = x1 - (space * math.cos(alphar)) y2 = p1[3] - space x2 = ((y2 - (m - (2 * space))) / k) scx = x1 scy = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # # Top line # p1 = Points[1] x1 = x2 y1 = y2 x2 = p1[2] + (space * math.sin(alphar)) y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # p1 = Points[2] k = p1[4] m = p1[5] x1 = x2 y1 = y2 y2 = (0 - ((PadSize / 2) + PadDistance)) x2 = ((y2 - m) / k) y2 = y2 - (space * math.sin(alphar)) x2 = p1[2] + space y2 = p1[3] fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # # Right side line # p1 = Points[3] k = p1[4] m = p1[5] x1 = p1[0] + space y1 = p1[1] x2 = x1 y2 = p1[3] + (space * math.sin(alphar)) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # p1 = Points[4] k = p1[4] m = p1[5] y1 = y2 x1 = x2 y2 = p1[3] + space x2 = ((y2 - (m + (2 * space))) / k) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # # Bottom line # p1 = Points[5] x1 = x2 y1 = y2 x2 = p1[2] - (space * math.sin(alphar)) y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # p1 = Points[6] x1 = x2 y1 = y2 x2 = p1[2] y2 = p1[3] y2 = y2 + (space * math.sin(alphar)) x2 = x2 - (space * math.cos(alphar)) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # # Left side line # p1 = Points[7] x1 = x2 y1 = y2 x2 = x1 y2 = scy fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) x1 = x2 y1 = y2 x2 = scx y2 = scy fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) # Pin1x1 = x1 Pin1y1 = scy RefX1 = 10.0 elif Type == 3: # # This have the shape of a box # # # Add the component outline # x1 = 0 - ((L - A) / 2) y1 = 0 - ((W - B) / 2) x2 = x1 + L y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 y2 = y1 + W fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 - L y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 y2 = 1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = x1 + 1 y2 = y1 - 1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = 0 - ((L - A) / 2) y2 = -1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) x1 = x2 y1 = y2 x2 = 0 - ((L - A) / 2) y2 = 0 - ((W - B) / 2) fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.Fab',width=0.1)) # # Add the component outline # x1 = (0 - ((L - A) / 2)) - 0.12 y1 = (0 - ((W - B) / 2)) - 0.12 x2 = x1 + L + 0.24 y2 = y1 if (y1 > ((PadSize / 2) + 0.25)): x1 = ((PadSize / 2) + 0.5) x2 = A - (PadSize / 2) - 0.5 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # x1 = x1 + L + 0.24 y1 = y2 x2 = x1 y2 = y1 + W + 0.24 if (x1 < (A + ((PadSize / 2) + 0.25))): y1 = (PadSize / 2) + 0.5 y2 = B - (PadSize / 2) - 0.5 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # x1 = x1 y1 = (0 - ((W - B) / 2)) + W + 0.12 x2 = (0 - ((L - A) / 2)) - 0.12 y2 = y1 if (y2 < (B + ((PadSize / 2) + 0.25))): x1 = ((PadSize / 2) + 0.5) x2 = A - (PadSize / 2) - 0.5 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # x1 = x2 y1 = y2 x2 = x1 y2 = (0 - ((W - B) / 2)) - 0.12 if (x1 > (0 - ((PadSize / 2) + 0.25))): y1 = (PadSize / 2) + 0.5 y2 = B - (PadSize / 2) - 0.5 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) # # Add the component courtyard # x1 = (0 - ((L - A) / 2)) - 0.25 y1 = (0 - ((W - B) / 2)) - 0.25 if (x1 > (0 - ((PadSize / 2) + 0.25))): x1 = 0 - ((PadSize / 2) + 0.25) if (y1 > (0 - ((PadSize / 2) + 0.25))): y1 = 0 - ((PadSize / 2) + 0.25) Pin1x1 = x1 Pin1y1 = y1 x2 = x1 + A - Pin1x1 y2 = y1 + B - Pin1y1 if (x2 < (A + ((L - A) / 2) + 0.25)): x2 = (A + ((L - A) / 2) + 0.25) if (y2 < (B + ((W - B) / 2) + 0.25)): y2 = (B + ((W - B) / 2) + 0.25) if (x2 < (A + (PadSize / 2) + 0.25)): x2 = (A + (PadSize / 2) + 0.25) if (y2 < (B + (PadSize / 2) + 0.25)): y2 = (B + (PadSize / 2) + 0.25) fp.append(RectLine(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.CrtYd',width=0.05)) RefX1 = 0.0 RefY1 = 0 - (((W - B) / 2) + 2) # # Add Pin 1 marker # x1 = Pin1x1 - 0.25 y1 = Pin1y1 - 0.25 x2 = x1 + Pin1dx y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) x1 = x1 y1 = y1 x2 = x1 y2 = y1 + 3.0 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer='F.SilkS',width=0.12)) fp.setTags(tags) fp.setDescription(description) # # Set general values # fp.append(Text(type='reference', text='REF**', at=[RefX1, RefY1], layer='F.SilkS')) fp.append(Text(type='value', text=fp_name, at=[round((A / 2), 2), round(((W - B) / 2) + B + 1.5, 2)], layer='F.Fab')) fp.append(Text(type='user', text="%R", at=[round((A / 2), 2), round((B / 2), 2)], layer='F.Fab')) # # Add 3D model # fp.append(Model(filename="${KISYS3DMOD}/" + TargetDir + "/" + fp_name + ".wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # # Add pads # fp.append(Pad(number=1,at=[0, 0], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam + 0.1, 2))) fp.append(Pad(number=2,at=[A, 0], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam + 0.1, 2))) fp.append(Pad(number=3,at=[0, B], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam + 0.1, 2))) fp.append(Pad(number=4,at=[A, B], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam + 0.1, 2))) #filename filename = output_dir + fp_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) ================================================ FILE: scripts/Inductors/Murata_DEM35xxC.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) from KicadModTree import * datasheet = "https://www.murata.com/~/media/webrenewal/products/inductor/chip/tokoproducts/wirewoundferritetypeforpl/m_dem3518c.ashx" footprint_name = "L_Murata_DEM35xxC" pkgWidth = 3.9 pkgHeight = 3.7 padXSpacing = 3.3 padWidth = 1 padHeight = 1.4 f = Footprint(footprint_name) f.setDescription(datasheet) f.setTags("Inductor SMD DEM35xxC") f.setAttribute("smd") f.append(Model(filename="${KISYS3DMOD}/Inductor_SMD.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) padSize = [padWidth, padHeight] textSize = [1.0, 1.0] fabRefTextSize = [0.7, 0.7] thickness1 = 0.1 thickness2 = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 crtYd = 0.25 silkClearance = 0.2 xCenter = 0.0 xPadRight = padXSpacing / 2 xFabRight = pkgWidth / 2 xSilkRight = xPadRight xRightCrtYd = max(xPadRight + padWidth / 2, xFabRight) + crtYd xLeftCrtYd = - xRightCrtYd xPadLeft = -xPadRight xFabLeft = -xFabRight xSilkTopLeft = -xSilkRight xSilkBottomLeft = -xSilkRight yCenter = 0.0 yFabBottom = pkgHeight / 2 ySilkBottom = yFabBottom + silkClearance yBottomCrtYd = yFabBottom + crtYd yTopCrtYd = -yBottomCrtYd ySilkTop = -ySilkBottom yFabTop = -yFabBottom yValue = yFabBottom + 1.25 yRef = yFabTop - 1.25 f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=textSize, thickness=thickness2)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=textSize, thickness=thickness2)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=fabRefTextSize, thickness=thickness1)) f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) f.append(PolygoneLine(polygone=[[xFabLeft, yFabTop], [xFabRight, yFabTop], [xFabRight, yFabBottom], [xFabLeft, yFabBottom], [xFabLeft, yFabTop]], layer="F.Fab", width=wFab)) f.append(Line(start=[xSilkTopLeft, ySilkTop], end=[xSilkRight, ySilkTop], layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xSilkBottomLeft, ySilkBottom], end=[xSilkRight, ySilkBottom], layer="F.SilkS", width=wSilkS)) padShape = Pad.SHAPE_ROUNDRECT radiusRatio = 0.2 f.append(Pad(number=1, type=Pad.TYPE_SMT, shape=padShape, at=[xPadLeft, yCenter], size=padSize, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) f.append(Pad(number=2, type=Pad.TYPE_SMT, shape=padShape, at=[xPadRight, yCenter], size=padSize, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") ================================================ FILE: scripts/Inductors/bourns-srn.py ================================================ #http://katalog.we-online.com/en/pbs/WE-MAPI] #sizes,shapes,etc] #name, L, W, pad-w, pad-gap, pad-h inductors = [ [1610,1.6,1.6,1.8,0.4,1.8], [2010,2.0,1.6,2.3,0.6,1.9], [2506,2.5,2.0,2.8,1.1,2.3], [2508,2.5,2.0,2.8,1.1,2.3], [2510,2.5,2.0,2.8,1.1,2.3], [2512,2.5,2.0,2.8,1.1,2.3], [3010,3.0,3.0,3.4,0.8,3.4], [3012,3.0,3.0,3.4,0.8,3.4], [3015,3.0,3.0,3.4,0.8,3.4], [3020,3.0,3.0,3.5,0.8,3.4], [4020,4.0,4.0,3.35,1.39,3.7], ] import sys import os output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append("..\\..") from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray prefix = "Inductor_" part = "Wurth_MAPI-{pn}" dims = "{l:0.1f}mmx{w:0.1f}mm" desc = "Inductor, Wurth Elektronik, {pn}" tags = "inductor wurth smd" for inductor in inductors: name,l,w,x,g,y = inductor fp_name = prefix + part.format(pn=str(name)) fp = Footprint(fp_name) description = desc.format(pn = part.format(pn=str(name))) + ", " + dims.format(l=l,w=w) fp.setTags(tags) fp.setAttribute("smd") fp.setDescription(description) # set general values fp.append(Text(type='reference', text='REF**', at=[0,-y/2 - 1], layer='F.SilkS')) fp.append(Text(type='value', text=fp_name, at=[0,y/2 + 1.5], layer='F.Fab')) #calculate pad center #pad-width pw pw = (x-g) / 2 c = g/2 + pw/2 #add the component outline fp.append(RectLine(start=[-l/2,-w/2],end=[l/2,w/2],layer='F.Fab',width=0.15)) layers = ["F.Cu","F.Paste","F.Mask"] #add pads fp.append(Pad(number=1,at=[-c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[pw,y])) fp.append(Pad(number=2,at=[c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[pw,y])) #add inductor courtyard cx = c + pw/2 cy = y / 2 fp.append(RectLine(start=[-cx,-cy],end=[cx,cy],offset=0.35,width=0.05,grid=0.05,layer="F.CrtYd")) #add lines fp.append(Line(start=[-g/2+0.2,-w/2-0.1],end=[g/2-0.2,-w/2-0.1])) fp.append(Line(start=[-g/2+0.2,w/2+0.1],end=[g/2-0.2,w/2+0.1])) #Add a model fp.append(Model(filename="Inductors.3dshapes/" + fp_name + ".wrl")) #filename filename = output_dir + fp_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) ================================================ FILE: scripts/Inductors/generator for normal packages found under SMD_chip_package_rlc-etc ================================================ ================================================ FILE: scripts/Inductors/vishay_IHSM.py ================================================ """ vishay IHSM series inductors http://www.vishay.com/docs/34018/ihsm3825.pdf http://www.vishay.com/docs/34019/ihsm4825.pdf http://www.vishay.com/docs/34020/ihsm5832.pdf http://www.vishay.com/docs/34021/ihsm7832.pdf """ #sizes,shapes,etc] #name, L, W, pad-w, pad-w, pad-gap, pad-h, datasheet inductors = [ [3825, 11.18, 6.35, 4.6, 5.6, 5.08, "http://www.vishay.com/docs/34018/ihsm3825.pdf"], [4825, 13.72, 6.35, 4.6, 5.6, 7.62, "http://www.vishay.com/docs/34019/ihsm4825.pdf"], [5832, 16.26, 8.13, 6.6, 7.4, 8.763, "http://www.vishay.com/docs/34020/ihsm5832.pdf"], [7382, 21.34, 8.13, 6.6, 7.4, 13.462, "http://www.vishay.com/docs/34021/ihsm7832.pdf"] ] import sys import os output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append("..\\..") from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray prefix = "Inductor_" part = "Vishay_IHSM-{pn}" dims = "{l:0.1f}mmx{w:0.1f}mm" desc = "Inductor, Vishay, {pn}, {datasheet}" tags = "inductor vishay icsm smd" for inductor in inductors: name,l,w,x,y,g,datasheet = inductor #pad center pos c = g/2 + x/2 fp_name = prefix + part.format(pn=str(name)) fp = Footprint(fp_name) description = desc.format(pn = part.format(pn=str(name)), datasheet=datasheet) + ", " + dims.format(l=l,w=w) fp.setTags(tags) fp.setAttribute("smd") fp.setDescription(description) #add inductor courtyard cx = max(l/2, (c+x/2)) cy = max(w/2, y/2) fp.append(RectLine(start=[-cx,-cy],end=[cx,cy],offset=0.35,width=0.05,grid=0.05,layer="F.CrtYd")) # set general values fp.append(Text(type='reference', text='REF**', at=[0,-cy - 1], layer='F.SilkS')) fp.append(Text(type='value', text=fp_name, at=[0,cy + 1.5], layer='F.Fab')) #calculate pad center #pad-width pw pw = x #add the component outline fp.append(RectLine(start=[-l/2,-w/2],end=[l/2,w/2],layer='F.Fab',width=0.15)) layers = ["F.Cu","F.Paste","F.Mask"] #add pads fp.append(Pad(number=1,at=[-c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[x,y])) fp.append(Pad(number=2,at=[c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[x,y])) poly = [ {'x': -l/2-0.1,'y': -y/2-0.3}, {'x': -l/2-0.1,'y': -w/2-0.1}, {'x': 0,'y': -w/2-0.1}, ] fp.append(PolygoneLine(polygone=poly)) fp.append(PolygoneLine(polygone=poly, x_mirror=0)) fp.append(PolygoneLine(polygone=poly, y_mirror=0)) fp.append(PolygoneLine(polygone=poly, x_mirror=0)) #Add a model fp.append(Model(filename="Inductors.3dshapes/" + fp_name + ".wrl")) #filename filename = output_dir + fp_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) print(fp_name) ================================================ FILE: scripts/Inductors/we-hci.py ================================================ #http://katalog.we-online.com/en/pbs/WE-MAPI] #sizes,shapes,etc] #name, L, W, pad-w, pad-gap, pad-h inductors = [ [5040,5.5,5.2,1.9,2.2,1.6], [7030,6.9,6.9,2.7,2.4,2.2], [7040,6.9,6.9,2.7,2.4,2.2], [7050,6.9,6.9,2.7,2.4,2.2], [1030,10.6,10.6,3.8,3.9,3.5], [1040,10.2,10.2,3.5,4.5,4], [1050,10.2,10.2,3.85,3.8,4], [1335,12.8,12.8,3.85,6.3,5], [1350,12.8,12.8,4.5,6,5], [1365,12.8,12.8,4.5,6,5], [2212,22.5,22.0,7,9.5,7], [1890,18.2,18.2,6,7.3,6], [1890,18.2,18.2,6,7.3,6], ] import sys import os output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append("..\\..") from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray prefix = "Inductor_" part = "Wurth_HCI-{pn}" dims = "{l:0.1f}mmx{w:0.1f}mm" desc = "Inductor, Wurth Elektronik, {pn}" tags = "inductor wurth hci smd" for inductor in inductors: name,l,w,x,g,y = inductor fp_name = prefix + part.format(pn=str(name)) fp = Footprint(fp_name) description = desc.format(pn = part.format(pn=str(name))) + ", " + dims.format(l=l,w=w) fp.setTags(tags) fp.setAttribute("smd") fp.setDescription(description) # set general values fp.append(Text(type='reference', text='REF**', at=[0,-w/2 - 1], layer='F.SilkS')) fp.append(Text(type='value', text=fp_name, at=[0,w/2 + 1.5], layer='F.Fab')) #add inductor outline fp.append(RectLine(start=[-l/2,-w/2],end=[l/2,w/2],layer='F.Fab',width=0.15)) #calculate pad center #pad-width pw pw = x c = g/2 + pw/2 layers = ["F.Cu","F.Paste","F.Mask"] #add pads fp.append(Pad(number=1,at=[-c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[pw,y])) fp.append(Pad(number=2,at=[c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[pw,y])) #add inductor courtyard cx = c + pw/2 cy = w / 2 fp.append(RectLine(start=[-cx,-cy],end=[cx,cy],offset=0.3,width=0.05,grid=0.05,layer="F.CrtYd")) offset = 0.1 ly = y/2 + 4 * offset x1 = l / 2 + offset y1 = w / 2 + offset top = [ {'x': -x1, 'y': ly}, {'x': -x1, 'y': y1}, {'x': x1, 'y': y1}, {'x': x1, 'y': ly}, ] fp.append(PolygoneLine(polygone=top)) fp.append(PolygoneLine(polygone=top,y_mirror=0)) #Add a model fp.append(Model(filename="Inductors.3dshapes/" + fp_name + ".wrl")) #filename filename = output_dir + fp_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) ================================================ FILE: scripts/Inductors/we-hcm.py ================================================ #http://katalog.we-online.com/en/pbs/WE-MAPI] #sizes,shapes,etc] #name, L, W, pad-w, pad-gap, pad-h inductors = [ [7050, 7.15, 7, 2, 3.3, 3.1], [7070, 7.4, 7.2, 2.55, 2.5, 2.2], [1050, 10.2, 7, 2, 6.35, 3.05], [1070, 10.1, 7, 3.6, 4, 2.6], [1078, 9.4, 6.2, 3.2, 4, 2.54], [1052, 10.5, 10.3, 2.45, 5.8, 2.7], [1190, 10.5, 11, 4, 4.2, 2.7], [1240, 10, 11.8, 2.6, 6.8, 4.5], [1350, 13.5, 13.3, 2.9, 8, 5.4], [1390, 12.5, 13, 2.5, 10, 5] ] import sys import os output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append("..\\..") from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray prefix = "Inductor_" part = "Wurth_HCM-{pn}" dims = "{l:0.1f}mmx{w:0.1f}mm" desc = "Inductor, Wurth Elektronik, {pn}" tags = "inductor wurth hcm smd" for inductor in inductors: name,l,w,x,g,y = inductor #pad center pos c = g/2 + x/2 fp_name = prefix + part.format(pn=str(name)) fp = Footprint(fp_name) description = desc.format(pn = part.format(pn=str(name))) + ", " + dims.format(l=l,w=w) fp.setTags(tags) fp.setAttribute("smd") fp.setDescription(description) #add inductor courtyard cx = max(l/2, (c+x/2)) cy = max(w/2, y/2) fp.append(RectLine(start=[-cx,-cy],end=[cx,cy],offset=0.35,width=0.05,grid=0.05,layer="F.CrtYd")) # set general values fp.append(Text(type='reference', text='REF**', at=[0,-cy - 1], layer='F.SilkS')) fp.append(Text(type='value', text=fp_name, at=[0,cy + 1.5], layer='F.Fab')) #calculate pad center #pad-width pw pw = x #add the component outline fp.append(RectLine(start=[-l/2,-w/2],end=[l/2,w/2],layer='F.Fab',width=0.15)) layers = ["F.Cu","F.Paste","F.Mask"] #add pads fp.append(Pad(number=1,at=[-c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[x,y])) fp.append(Pad(number=2,at=[c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[x,y])) poly = [ {'x': -l/2-0.1,'y': -y/2-0.3}, {'x': -l/2-0.1,'y': -w/2-0.1}, {'x': 0,'y': -w/2-0.1}, ] fp.append(PolygoneLine(polygone=poly)) fp.append(PolygoneLine(polygone=poly, x_mirror=0)) fp.append(PolygoneLine(polygone=poly, y_mirror=0)) fp.append(PolygoneLine(polygone=poly, x_mirror=0)) #Add a model fp.append(Model(filename="Inductors.3dshapes/" + fp_name + ".wrl")) #filename filename = output_dir + fp_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) print(fp_name) ================================================ FILE: scripts/Inductors/we-mapi.py ================================================ #http://katalog.we-online.com/en/pbs/WE-MAPI] #sizes,shapes,etc] #name, L, W, pad-w, pad-gap, pad-h inductors = [ [1610,1.6,1.6,1.8,0.4,1.8], [2010,2.0,1.6,2.3,0.6,1.9], [2506,2.5,2.0,2.8,1.1,2.3], [2508,2.5,2.0,2.8,1.1,2.3], [2510,2.5,2.0,2.8,1.1,2.3], [2512,2.5,2.0,2.8,1.1,2.3], [3010,3.0,3.0,3.4,0.8,3.4], [3012,3.0,3.0,3.4,0.8,3.4], [3015,3.0,3.0,3.4,0.8,3.4], [3020,3.0,3.0,3.5,0.8,3.4], [4020,4.0,4.0,3.35,1.39,3.7], ] import sys import os output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append("..\\..") from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray prefix = "Inductor_" part = "Wurth_MAPI-{pn}" dims = "{l:0.1f}mmx{w:0.1f}mm" desc = "Inductor, Wurth Elektronik, {pn}" tags = "inductor wurth smd" for inductor in inductors: name,l,w,x,g,y = inductor fp_name = prefix + part.format(pn=str(name)) fp = Footprint(fp_name) description = desc.format(pn = part.format(pn=str(name))) + ", " + dims.format(l=l,w=w) fp.setTags(tags) fp.setAttribute("smd") fp.setDescription(description) # set general values fp.append(Text(type='reference', text='REF**', at=[0,-y/2 - 1], layer='F.SilkS')) fp.append(Text(type='value', text=fp_name, at=[0,y/2 + 1.5], layer='F.Fab')) #calculate pad center #pad-width pw pw = (x-g) / 2 c = g/2 + pw/2 #add the component outline fp.append(RectLine(start=[-l/2,-w/2],end=[l/2,w/2],layer='F.Fab',width=0.15)) layers = ["F.Cu","F.Paste","F.Mask"] #add pads fp.append(Pad(number=1,at=[-c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[pw,y])) fp.append(Pad(number=2,at=[c,0],layers=layers,shape=Pad.SHAPE_RECT,type=Pad.TYPE_SMT,size=[pw,y])) #add inductor courtyard cx = c + pw/2 cy = y / 2 fp.append(RectLine(start=[-cx,-cy],end=[cx,cy],offset=0.35,width=0.05,grid=0.05,layer="F.CrtYd")) #add lines fp.append(Line(start=[-g/2+0.2,-w/2-0.1],end=[g/2-0.2,-w/2-0.1])) fp.append(Line(start=[-g/2+0.2,w/2+0.1],end=[g/2-0.2,w/2+0.1])) #Add a model fp.append(Model(filename="Inductors.3dshapes/" + fp_name + ".wrl")) #filename filename = output_dir + fp_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) ================================================ FILE: scripts/LEDs_SMD/generator for normal packages found under SMD_chip_package_rlc-etc ================================================ ================================================ FILE: scripts/LEDs_SMD/plcc4.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) from KicadModTree import * def plcc4(args): footprint_name = args["name"] pkgWidth = args["pkg_width"] pkgHeight = args["pkg_height"] padXSpacing = args["pad_x_spacing"] padYSpacing = args["pad_y_spacing"] padWidth = args["pad_width"] padHeight = args["pad_height"] pads_clockwise = args["pads_clockwise"] desc = str(pkgWidth) + "mm x " + str(pkgHeight) + "mm PLCC4 LED, " f = Footprint(footprint_name) f.setDescription(desc + args["datasheet"]) f.setTags("LED Cree PLCC-4") f.setAttribute("smd") f.append(Model(filename="${KISYS3DMOD}/LEDs.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) p = [padWidth, padHeight] r = pkgHeight * 0.4 s = [1.0, 1.0] sFabRef = [0.5, 0.5] t1 = 0.075 t2 = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 crtYd = 0.25 silkClearance = 0.2 xCenter = 0.0 xPadRight = padXSpacing / 2 xFabRight = pkgWidth / 2 xSilkRight = xPadRight + padWidth / 2 + silkClearance xRightCrtYd = xSilkRight + crtYd xLeftCrtYd = -xRightCrtYd xSilkLeft = -xSilkRight xPadLeft = -xPadRight xFabLeft = -xFabRight xChamfer = xFabLeft + 1.0 yCenter = 0.0 yPadBottom = padYSpacing / 2 yFabBottom = pkgHeight / 2 ySilkBottom = max(yFabBottom + 0.1, yPadBottom + padHeight / 2 + silkClearance) yBottomCrtYd = ySilkBottom + crtYd yTopCrtYd = -yBottomCrtYd ySilkTop = -ySilkBottom yFabTop = -yFabBottom yPadTop = -yPadBottom yChamfer = yFabTop + 1 yValue = yFabBottom + 1.25 yRef = yFabTop - 1.25 f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s, thickness=t2)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s, thickness=t2)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=sFabRef, thickness=t1)) f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) f.append(Line(start=[xChamfer, yFabTop], end=[xFabLeft, yChamfer], layer="F.Fab", width=wFab)) f.append(RectLine(start=[xFabLeft, yFabTop], end=[xFabRight, yFabBottom], layer="F.Fab", width=wFab)) f.append(Circle(center=[xCenter, yCenter], radius=r, layer="F.Fab", width=wFab)) f.append(PolygoneLine(polygone=[[xSilkLeft, yPadTop], [xSilkLeft, ySilkTop], [xSilkRight, ySilkTop]], layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xSilkLeft, ySilkBottom], end=[xSilkRight, ySilkBottom], layer="F.SilkS", width=wSilkS)) if pads_clockwise: pads = ["1", "2", "3", "4"] else: pads = ["1", "4", "3", "2"] f.append(Pad(number=pads[0], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xPadLeft, yPadTop], size=p, layers=Pad.LAYERS_SMT)) f.append(Pad(number=pads[1], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xPadRight, yPadTop], size=p, layers=Pad.LAYERS_SMT)) f.append(Pad(number=pads[2], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xPadRight, yPadBottom], size=p, layers=Pad.LAYERS_SMT)) f.append(Pad(number=pads[3], type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xPadLeft, yPadBottom], size=p, layers=Pad.LAYERS_SMT)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(plcc4) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("datasheet", type=str, required=True) parser.add_parameter("pkg_width", type=float, required=False, default=2.0) parser.add_parameter("pkg_height", type=float, required=False, default=2.0) parser.add_parameter("pad_x_spacing", type=float, required=False, default=1.5) parser.add_parameter("pad_y_spacing", type=float, required=False, default=1.1) parser.add_parameter("pad_width", type=float, required=False, default=1.0) parser.add_parameter("pad_height", type=float, required=False, default=0.8) parser.add_parameter("pads_clockwise", type=bool, required=False, default=True) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/LEDs_SMD/plcc4.yml ================================================ LED_Cree-PLCC4_2x2mm_CW: datasheet: http://www.cree.com/~/media/Files/Cree/LED-Components-and-Modules/HB/Data-Sheets/CLMVBFKA.pdf pkg_width: 2.0 pkg_height: 2.0 pad_x_spacing: 1.5 pad_y_spacing: 1.1 pad_width: 1.0 pad_height: 0.8 pads_clockwise: true LED_Cree-PLCC4_3.2x2.8mm_CCW: datasheet: http://www.cree.com/led-components/media/documents/CLV1AFKB(874).pdf pkg_width: 3.2 pkg_height: 2.8 pad_x_spacing: 2.5 pad_y_spacing: 1.4 pad_width: 1.0 pad_height: 0.8 pads_clockwise: false ================================================ FILE: scripts/LEDs_SMD/smlvn6.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) from KicadModTree import * datasheet = "https://www.rohm.com/datasheet/SMLVN6RGB1U" footprint_name = "LED_ROHM_SMLVN6" pkgWidth = 3.1 pkgHeight = 2.8 padXSpacing = 3.05 padYSpacing = 1.05 padWidth = 1.45 padHeight = 0.6 padCornerHeight = 0.8 f = Footprint(footprint_name) f.setDescription(datasheet) f.setTags("LED ROHM SMLVN6") f.setAttribute("smd") f.append(Model(filename="${KISYS3DMOD}/LED_SMD.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) p = [padWidth, padHeight] pCorner = [padWidth, padCornerHeight] s = [1.0, 1.0] sFabRef = [0.7, 0.7] t1 = 0.1 t2 = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 crtYd = 0.3 silkClearance = 0.2 xCenter = 0.0 xPadRight = padXSpacing / 2 xFabRight = pkgWidth / 2 xSilkRight = xPadRight xRightCrtYd = max(xPadRight + padWidth / 2, xFabRight) + crtYd xLeftCrtYd = - xRightCrtYd xPadLeft = -xPadRight xFabLeft = -xFabRight xChamfer = xFabLeft + 1.0 xSilkTopLeft = -xSilkRight - (padWidth / 2) + (wSilkS / 2) xSilkBottomLeft = -xSilkRight yCenter = 0.0 yPadBottom = padYSpacing yFabBottom = pkgHeight / 2 yBottom = max(yFabBottom + 0.1, yPadBottom + padHeight / 2) ySilkBottom = yBottom + silkClearance yBottomCrtYd = yBottom + crtYd yTopCrtYd = -yBottomCrtYd ySilkTop = -ySilkBottom yFabTop = -yFabBottom yPadTop = -yPadBottom yChamfer = yFabTop + 1 yValue = yFabBottom + 1.25 yRef = yFabTop - 1.25 f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s, thickness=t2)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s, thickness=t2)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=sFabRef, thickness=t1)) f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) f.append(PolygoneLine(polygone=[[xFabLeft, yChamfer], [xChamfer, yFabTop], [xFabRight, yFabTop], [xFabRight, yFabBottom], [xFabLeft, yFabBottom], [xFabLeft, yChamfer]], layer="F.Fab", width=wFab)) f.append(Line(start=[xSilkTopLeft, ySilkTop], end=[xSilkRight, ySilkTop], layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xSilkBottomLeft, ySilkBottom], end=[xSilkRight, ySilkBottom], layer="F.SilkS", width=wSilkS)) pads = ["1", "6", "2", "5", "3", "4"] padShape = Pad.SHAPE_ROUNDRECT radiusRatio = 0.2 f.append(Pad(number=pads[0], type=Pad.TYPE_SMT, shape=padShape, at=[xPadLeft, yPadTop], size=pCorner, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) f.append(Pad(number=pads[1], type=Pad.TYPE_SMT, shape=padShape, at=[xPadRight, yPadTop], size=pCorner, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) f.append(Pad(number=pads[2], type=Pad.TYPE_SMT, shape=padShape, at=[xPadLeft, yCenter], size=p, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) f.append(Pad(number=pads[3], type=Pad.TYPE_SMT, shape=padShape, at=[xPadRight, yCenter], size=p, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) f.append(Pad(number=pads[4], type=Pad.TYPE_SMT, shape=padShape, at=[xPadLeft, yPadBottom], size=pCorner, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) f.append(Pad(number=pads[5], type=Pad.TYPE_SMT, shape=padShape, at=[xPadRight, yPadBottom], size=pCorner, layers=Pad.LAYERS_SMT, radius_ratio=radiusRatio)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") ================================================ FILE: scripts/LEDs_THT/make_LEDs_THT.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_LEDs import * if __name__ == '__main__': # standard resistors: http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf type = "round" script3d_rv="leds_round_ver.py" with open(script3d_rv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_rh="leds_round_hor.py" with open(script3d_rh, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_reh="leds_rect_hor.py" with open(script3d_reh, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_rreh="leds_rect_round_hor.py" with open(script3d_rreh, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") d2=0 R_POW = 0 clname="LED" lbname="LEDs" ddrill = 0.9 type="round"; pins=2; rm=2.54; rin=3; w=3.8; h=w; height3d=4.3; height3d_bottom=1; name_additions=[]; specialtags=[]; add_description="" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins = 3; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-3VSURKCGKC(Ver.8A).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins=2; rm=2.54; rin=5; w=5.8; h=w; height3d=7.6; height3d_bottom=1; name_additions=[]; specialtags=[]; add_description="http://cdn-reichelt.de/documents/datenblatt/A500/LL-504BC2E-009.pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins = 3; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-59EGC(Ver.17A).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins = 4; rm=1.27; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-154A4SUREQBFZGEW(Ver.9A).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins=2; rm=2.54; rin=4; w=4.8; h=w; height3d=6; height3d_bottom=1; name_additions=[]; specialtags=[]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-43GD(Ver.12B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins=2; rm=2.54; rin=8; w=9; h=w; height3d=9; height3d_bottom=2; name_additions=[]; specialtags=[]; add_description="http://cdn-reichelt.de/documents/datenblatt/A500/LED8MMGE_LED8MMGN_LED8MMRT%23KIN.pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins = 3; add_description="" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins=2; rm=2.54; rin=10; w=11; h=w; height3d=11.5; height3d_bottom=2; name_additions=[]; specialtags=[]; add_description="http://cdn-reichelt.de/documents/datenblatt/A500/LED10-4500RT%23KIN.pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins = 3; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-819EGW(Ver.14A).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) pins=2; rm=2.54; rin=20; w=23; h=w; height3d=10; height3d_bottom=3.5; name_additions=[]; specialtags=[]; add_description="http://cdn-reichelt.de/documents/datenblatt/A500/DLC2-6GD%28V6%29.pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname, lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="oval"; pins=2; rm=2.54; rin=0; w=5.2; h=3.8; height3d=7; height3d_bottom=0; name_additions=[]; specialtags=["Oval"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-5603QBC-D(Ver.12B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_Oval", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=2; w=4.8; h=2.5; height3d=4.5; height3d_bottom=3.5; name_additions=["FlatTop"]; specialtags=["Round", "FlatTop"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-13GD(Ver.11B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=1.8; w=3.3; h=2.4; height3d=1.4; height3d_bottom=1.6; name_additions=[]; specialtags=["Round"]; add_description="" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="round"; pins=2; rm=2.54; rin=3; w=3.8; h=w; height3d=4.8; height3d_bottom=6-4.8; name_additions=["FlatTop"]; specialtags=["Round","FlatTop"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-47XEC(Ver.9A).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="round"; pins=2; rm=2.54; rin=5; w=5.9; h=w; height3d=8.6; height3d_bottom=1; name_additions=["FlatTop"]; specialtags=["Round","FlatTop"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-483GDT(Ver.15B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=2; w=4; h=2.8; height3d=1.95; height3d_bottom=5-1.95; name_additions=["FlatTop"]; specialtags=["Round","FlatTop"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-1034IDT(Ver.9A).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=0; w=3.9; h=1.75; height3d=7; height3d_bottom=0; name_additions=["FlatTop"]; specialtags=["Rectangular"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-2774GD(Ver.7B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_Rectangular", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=0; w=3.9; h=1.9; height3d=7; height3d_bottom=0; name_additions=[]; specialtags=["Rectangular"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-144GDT(Ver.14B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_Rectangular", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=0; w=3; h=2; height3d=7; height3d_bottom=0; name_additions=[]; specialtags=["Rectangular"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-169XCGDK(Ver.9B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_Rectangular", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=0; w=5; h=2; height3d=9.7; height3d_bottom=0; name_additions=[]; specialtags=["Rectangular"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-169XCGDK(Ver.9B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_Rectangular", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=3; rm=2.54; rin=0; w=5; h=2; height3d=9.7; height3d_bottom=0; name_additions=[]; specialtags=["Rectangular"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-169XCGDK(Ver.9B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_Rectangular", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=0; w=5; h=5; height3d=9.7; height3d_bottom=0; name_additions=[]; specialtags=["Rectangular"]; add_description="http://www.kingbright.com/attachments/file/psearch/000/00/00/L-169XCGDK(Ver.9B).pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_Rectangular", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="box"; pins=2; rm=2.54; rin=0; w=4.5; h=1.6; height3d=5.7; height3d_bottom=0; name_additions=[]; specialtags=["Rectangular","SideEmitter"]; add_description="http://cdn-reichelt.de/documents/datenblatt/A500/LED15MMGE_LED15MMGN%23KIN.pdf" makeLEDRadial(pins=pins, rm=rm, w=w, h=h, ddrill=ddrill, rin=rin, type=type, x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags, add_description=add_description, classname=clname+"_SideEmitter_Rectangular", lib_name=lbname,name_additions=name_additions, script3d=script3d_rv, height3d=height3d, height3d_bottom=height3d_bottom) type="round"; pins=2; rm=2.54; dled=3; dledout=3.8; offset=2.54;wled=5.3; height3d=3; name_additions=[]; specialtags=[]; add_description="" offsets=[1.27,3.81,6.35] for ledypos in [2,6,10]: for offset in offsets: makeLEDHorizontal(ledypos=ledypos, pins=pins, rm=rm, ddrill=ddrill,dled=dled, dledout=dledout, offsetled=offset, wled=wled, type=type, x_3d=[0, 0, 0],s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags,add_description=add_description,classname=clname, lib_name=lbname, name_additions=name_additions, script3d=script3d_rh, height3d=height3d) type="round"; pins=2; rm=2.54; dled=5; dledout=5.8; offset=2.54;wled=8.6; height3d=5; name_additions=[]; specialtags=[]; add_description="" for ledypos in [3,9,15]: for offset in offsets: makeLEDHorizontal(ledypos=ledypos, pins=pins, rm=rm, ddrill=ddrill,dled=dled, dledout=dledout, offsetled=offset, wled=wled, type=type, x_3d=[0, 0, 0],s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags,add_description=add_description,classname=clname, lib_name=lbname, name_additions=name_additions, script3d=script3d_rh, height3d=height3d) type="box"; pins=2; rm=2.54; dled=1.8; dledout=3.3; wled=3; wledback=1.6; height3d=2.4; height3d_bottom=1.6; name_additions=[]; specialtags=[""]; add_description="" for ledypos in [1.65, 1.65+3.3, 1.65+3.3*2]: for offset in offsets: makeLEDHorizontal(ledypos=ledypos, pins=pins, rm=rm, ddrill=ddrill,dled=dled, dledout=dledout, wledback=wledback, offsetled=offset, wled=wled, type=type, x_3d=[0, 0, 0],s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags,add_description=add_description,classname=clname+"", lib_name=lbname, name_additions=name_additions, script3d=script3d_rreh, height3d=height3d) type="box"; pins=2; rm=2.54; dled=5; dledout=5; wled=9.7; wledback=0; height3d=2; height3d_bottom=1.6; name_additions=[]; specialtags=["Rectangular"]; add_description="" for ledypos in [1, 3, 5]: for offset in offsets: makeLEDHorizontal(ledypos=ledypos, pins=pins, rm=rm, ddrill=ddrill,dled=dled, dledout=dledout, wledback=wledback, offsetled=offset, wled=wled, type=type, x_3d=[0, 0, 0],s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=specialtags,add_description=add_description,classname=clname+"_Rectangular", lib_name=lbname, name_additions=name_additions, script3d=script3d_reh, height3d=height3d) ================================================ FILE: scripts/Mounting_Hardware/mounting_hole.py ================================================ #!/usr/bin/env python import sys import os import argparse import yaml import math sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA # https://stackoverflow.com/questions/4265546/python-round-to-nearest-05 def round_to(n, precision): correction = 0.5 if n >= 0 else -0.5 return int(n/precision+correction) * precision def create_footprint(name, **kwargs): kicad_mod = Footprint(name) # init kicad footprint kicad_mod.setDescription(kwargs['description']) kicad_mod.setTags('Mounting Hole') # load some general values hole_x = float(kwargs['hole_x']) hole_y = float(kwargs['hole_y']) anular_ring = float(kwargs['anular_ring']) courtjard = float(kwargs['courtjard']) create_via = kwargs['via'] pad_x = hole_x + 2*anular_ring pad_y = hole_y + 2*anular_ring courtjard_x = pad_x + 2*courtjard courtjard_y = pad_y + 2*courtjard # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, -courtjard_y/2 - 0.75], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=name, at=[0, courtjard_y/2 + 0.75], layer='F.Fab')) # create courtyard if hole_x == hole_y: kicad_mod.append(Circle(center=[0, 0], radius=courtjard_x/2., layer='F.CrtYd')) elif hole_x > hole_y: courtjard_length_x = courtjard_x - courtjard_y kicad_mod.append(RectLine(start=[courtjard_length_x / 2, courtjard_y / 2], end=[-courtjard_length_x / 2, courtjard_y / 2], layer='F.CrtYd')) kicad_mod.append(RectLine(start=[courtjard_length_x / 2, -courtjard_y / 2], end=[-courtjard_length_x / 2, -courtjard_y / 2], layer='F.CrtYd')) kicad_mod.append(Arc(center=[courtjard_length_x/2 , 0], start=[courtjard_length_x / 2, -courtjard_y / 2], angle=180, layer='F.CrtYd')) kicad_mod.append(Arc(center=[-courtjard_length_x / 2, 0], start=[-courtjard_length_x / 2, courtjard_y / 2], angle=180, layer='F.CrtYd')) else: # hole_x < hole_y courtjard_length_y = courtjard_y - courtjard_x kicad_mod.append( RectLine(start=[courtjard_x / 2, courtjard_length_y / 2], end=[courtjard_x / 2, -courtjard_length_y / 2], layer='F.CrtYd')) kicad_mod.append( RectLine(start=[-courtjard_x / 2, courtjard_length_y / 2], end=[-courtjard_x / 2, -courtjard_length_y / 2], layer='F.CrtYd')) kicad_mod.append( Arc(center=[0, courtjard_length_y / 2], start=[courtjard_x / 2, courtjard_length_y / 2], angle=180, layer='F.CrtYd')) kicad_mod.append( Arc(center=[0, -courtjard_length_y / 2], start=[-courtjard_x / 2, -courtjard_length_y / 2], angle=180, layer='F.CrtYd')) # create pads pad_kwargs = { 'number': 1, 'type': Pad.TYPE_THT, 'at': [0, 0], 'size': [pad_x, pad_y], 'layers': ['*.Cu', '*.Mask'] } if hole_x == hole_y: kicad_mod.append(Pad(**pad_kwargs, shape=Pad.SHAPE_CIRCLE, drill=hole_x)) else: kicad_mod.append(Pad(**pad_kwargs, shape=Pad.SHAPE_OVAL, drill=[hole_x, hole_y])) # create via's if create_via: via_count = int(kwargs['via_count']) via_diameter = float(kwargs['via_diameter']) x_size = hole_x + anular_ring y_size = hole_y + anular_ring circle_radius = min(x_size, y_size) / 2 circle_scope = min(x_size, y_size) * math.pi if hole_x > hole_y: line_scope_x = 2 * (x_size - y_size) line_scope_y = 0 else: line_scope_x = 0 line_scope_y = 2 * (y_size - x_size) line_scope = line_scope_x + line_scope_y vias_scope = circle_scope + line_scope for step in range(via_count): scope_step = (vias_scope / via_count * step - line_scope_y / 4 + vias_scope) % vias_scope # align on right center if scope_step <= circle_scope / 4: local_scope_pos = scope_step circle_pos = local_scope_pos / circle_scope * 2 * math.pi step_x = math.cos(circle_pos) * circle_radius + line_scope_x / 4 step_y = math.sin(circle_pos) * circle_radius + line_scope_y / 4 elif scope_step <= circle_scope / 4 + line_scope_x / 2: local_scope_pos = scope_step - circle_scope / 4 step_x = line_scope_x / 4 - local_scope_pos step_y = y_size / 2 elif scope_step <= circle_scope / 2 + line_scope_x / 2: local_scope_pos = scope_step - line_scope_x / 2 # angle of circle already included circle_pos = local_scope_pos / circle_scope * 2 * math.pi step_x = math.cos(circle_pos) * circle_radius - line_scope_x / 4 step_y = math.sin(circle_pos) * circle_radius + line_scope_y / 4 elif scope_step <= circle_scope / 2 + line_scope_x / 2 + line_scope_y / 2: local_scope_pos = scope_step - circle_scope / 2 - line_scope_x / 2 step_x = -x_size / 2 step_y = line_scope_y / 4 - local_scope_pos elif scope_step <= 3 * circle_scope / 4 + line_scope_x / 2 + line_scope_y / 2: local_scope_pos = scope_step - line_scope_x / 2 - line_scope_y / 2 # angle of circle already included circle_pos = local_scope_pos / circle_scope * 2 * math.pi step_x = math.cos(circle_pos) * circle_radius - line_scope_x / 4 step_y = math.sin(circle_pos) * circle_radius - line_scope_y / 4 elif scope_step <= 3 * circle_scope / 4 + line_scope_x + line_scope_y / 2: local_scope_pos = scope_step - 3 * circle_scope / 4 - line_scope_x / 2 - line_scope_y / 2 step_x = -line_scope_x / 4 + local_scope_pos step_y = -y_size / 2 elif scope_step <= circle_scope + line_scope_x + line_scope_y / 2: local_scope_pos = scope_step - line_scope_x - line_scope_y / 2 # angle of circle already included circle_pos = local_scope_pos / circle_scope * 2 * math.pi step_x = math.cos(circle_pos) * circle_radius + line_scope_x / 4 step_y = math.sin(circle_pos) * circle_radius - line_scope_y / 4 elif scope_step < circle_scope + line_scope_x + line_scope_y: local_scope_pos = scope_step - circle_scope - line_scope_x - line_scope_y / 2 step_x = x_size / 2 step_y = -line_scope_y / 4 + local_scope_pos else: # error raise "invalid scope_step" kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[step_x, step_y], size=[via_diameter+0.1, via_diameter+0.1], drill=via_diameter, layers=['*.Cu', '*.Mask'])) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{name}.kicad_mod'.format(name=name)) def parse_and_execute_yml_file(filepath): with open(filepath, 'r') as stream: try: yaml_parsed = yaml.safe_load(stream) for footprint in yaml_parsed: print("generate {name}.kicad_mod".format(name=footprint)) create_footprint(footprint, **yaml_parsed.get(footprint)) except yaml.YAMLError as exc: print(exc) if __name__ == "__main__": parser = argparse.ArgumentParser(description='Parse *.kicad_mod.yml file(s) and create matching footprints') parser.add_argument('files', metavar='file', type=str, nargs='+', help='yml-files to parse') #parser.add_argument('-v', '--verbose', help='show more information when creating footprint', action='store_true') # TODO: allow writing into sub file args = parser.parse_args() for filepath in args.files: parse_and_execute_yml_file(filepath) ================================================ FILE: scripts/Mounting_Hardware/wuerth_smt_spacer.py ================================================ #!/usr/bin/env python3 import sys import os #sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path # export PYTHONPATH="${PYTHONPATH}" sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree import argparse import yaml from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields def roundToBase(value, base): return round(value/base) * base def generate_footprint(params, mpn, configuration): fp_params = params['footprint'] mech_params = params['mechanical'] part_params = params['parts'][mpn] if 'id' in mech_params: size = str(mech_params['id']) elif 'ext_thread' in mech_params: size = str(mech_params['ext_thread']['od']) if 'M' not in size: size = "{}mm".format(size) td = "" size_prefix = "" hole_type = "inside through hole" if 'thread_depth' in part_params: hole_type = "inside blind hole" td = "_ThreadDepth{}mm".format(part_params['thread_depth']) elif 'ext_thread' in mech_params: hole_type = "external" size_prefix = 'External' h = part_params['h'] if 'h' in part_params else part_params['h1'] suffix = '' if 'suffix' in params: suffix = '_{}'.format(params['suffix']) fp_name = "Mounting_Wuerth_{series}-{size_prefix}{size}_H{h}mm{td}{suffix}_{mpn}".format( size=size, h=h, mpn=mpn, td=td, size_prefix=size_prefix, series=params['series_prefix'], suffix=suffix) kicad_mod = Footprint(fp_name) kicad_mod.setAttribute('smd') kicad_mod.setDescription("Mounting Hardware, {hole_type} {size}, height {h}, Wuerth electronics {mpn} ({ds:s}), generated with kicad-footprint-generator".format(size=size, h=h, mpn=mpn, ds=part_params['datasheet'], hole_type=hole_type)) kicad_mod.setTags('Mounting {} {}'.format(size, mpn)) paste_count = fp_params['ring']['paste'].get('paste_count', 4) kicad_mod.append( RingPad( number='1', at=(0, 0), size=fp_params['ring']['od'], inner_diameter=fp_params['ring']['id'], num_anchor=4, num_paste_zones=paste_count, paste_round_radius_radio=0.25, paste_max_round_radius=0.1, paste_to_paste_clearance=fp_params['ring']['paste']['clearance'], paste_inner_diameter=fp_params['ring']['paste']['id'], paste_outer_diameter=fp_params['ring']['paste']['od'] )) if 'npth' in fp_params: kicad_mod.append( Pad(at=[0, 0], number="", type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, size=fp_params['npth'], drill=fp_params['npth'], layers=Pad.LAYERS_NPTH)) kicad_mod.append( Circle( center=[0, 0], radius=mech_params['od']/2, layer='F.Fab', width=configuration['fab_line_width'] )) ########################### CrtYd ################################# rc = max(mech_params['od'], fp_params['ring']['od'])/2+configuration['courtyard_offset']['default'] rc = roundToBase(rc, configuration['courtyard_grid']) kicad_mod.append( Circle( center=[0, 0], radius=rc, layer='F.CrtYd', width=configuration['courtyard_line_width'] )) ########################### SilkS ################################# ######################### Text Fields ############################### rb = mech_params['od']/2 body_edge={'left':-rb, 'right':rb, 'top':-rb, 'bottom':rb} addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top':-rc, 'bottom':rc}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ model3d_path_prefix = configuration.get('3d_model_prefix','${KISYS3DMOD}/') lib_name = "Mounting_Wuerth" model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name) kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--params', type=str, nargs='?', help='the part definition file', default='./wuerth_smt_spacer.yaml') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.params, 'r') as params_stream: try: params = yaml.safe_load(params_stream) except yaml.YAMLError as exc: print(exc) for series in params: for mpn in params[series]['parts']: generate_footprint(params[series], mpn, configuration) ================================================ FILE: scripts/Mounting_Hardware/wuerth_smt_spacer.yaml ================================================ 2.25mm: series_prefix: WA-SMST footprint: ring: id: 3 od: 5.3 paste: clearance: 0.6 id: 3.1 od: 5.12 npth: 3 mechanical: id: 2.25 od: 4.35 od1: 2.8 h1: 1.4 parts: 9774010943: datasheet: https://katalog.we-online.de/em/datasheet/9774010943.pdf h: 1 9774015943: datasheet: https://katalog.we-online.de/em/datasheet/9774015943.pdf h: 1.5 9774020943: datasheet: https://katalog.we-online.de/em/datasheet/9774020943.pdf h: 2 9774025943: datasheet: https://katalog.we-online.de/em/datasheet/9774025943.pdf h: 2.5 9774030943: datasheet: https://katalog.we-online.de/em/datasheet/9774030943.pdf h: 3 9774035943: datasheet: https://katalog.we-online.de/em/datasheet/9774035943.pdf h: 3.5 9774040943: datasheet: https://katalog.we-online.de/em/datasheet/9774040943.pdf h: 4 9774045943: datasheet: https://katalog.we-online.de/em/datasheet/9774045943.pdf h: 4.5 9774050943: datasheet: https://katalog.we-online.de/em/datasheet/9774050943.pdf h: 5 9774060943: datasheet: https://katalog.we-online.de/em/datasheet/9774060943.pdf h: 6 9774070943: datasheet: https://katalog.we-online.de/em/datasheet/9774070943.pdf h: 7 9774080943: datasheet: https://katalog.we-online.de/em/datasheet/9774080943.pdf h: 8 2.7mm: series_prefix: WA-SMST footprint: ring: id: 3.7 od: 6 paste: clearance: 0.65 id: 3.8 od: 5.84 npth: 3.7 mechanical: id: 2.7 od: 5.1 od1: 3.5 h1: 1.4 parts: 9774010951: datasheet: https://katalog.we-online.de/em/datasheet/9774010951.pdf h: 1 9774015951: datasheet: https://katalog.we-online.de/em/datasheet/9774015951.pdf h: 1.5 9774020951: datasheet: https://katalog.we-online.de/em/datasheet/9774020951.pdf h: 2 9774025951: datasheet: https://katalog.we-online.de/em/datasheet/9774025951.pdf h: 2.5 9774030951: datasheet: https://katalog.we-online.de/em/datasheet/9774030951.pdf h: 3 9774040951: datasheet: https://katalog.we-online.de/em/datasheet/9774040951.pdf h: 4 9774050951: datasheet: https://katalog.we-online.de/em/datasheet/9774050951.pdf h: 5 9774055951: datasheet: https://katalog.we-online.de/em/datasheet/9774055951.pdf h: 5.5 9774060951: datasheet: https://katalog.we-online.de/em/datasheet/9774060951.pdf h: 6 9774065951: datasheet: https://katalog.we-online.de/em/datasheet/9774065951.pdf h: 6.5 9774070951: datasheet: https://katalog.we-online.de/em/datasheet/9774070951.pdf h: 7 9774080951: datasheet: https://katalog.we-online.de/em/datasheet/9774080951.pdf h: 8 9774090951: datasheet: https://katalog.we-online.de/em/datasheet/9774090951.pdf h: 9 9774100951: datasheet: https://katalog.we-online.de/em/datasheet/9774100951.pdf h: 10 3.3mm: series_prefix: WA-SMST footprint: ring: id: 4.4 od: 7.4 paste: # measured from eagle footprint (not dimensioned in datasheet) clearance: 0.5 id: 4.72 od: 6.92 npth: 4.4 mechanical: id: 3.3 od: 6 od1: 4.2 h1: 1.4 parts: 9774010960: datasheet: https://katalog.we-online.de/em/datasheet/9774010960.pdf, h: 1 9774015960: datasheet: https://katalog.we-online.de/em/datasheet/9774015960.pdf, h: 1.5 9774020960: datasheet: https://katalog.we-online.de/em/datasheet/9774020960.pdf, h: 2 9774025960: datasheet: https://katalog.we-online.de/em/datasheet/9774025960.pdf, h: 2.5 9774030960: datasheet: https://katalog.we-online.de/em/datasheet/9774030960.pdf, h: 3 9774040960: datasheet: https://katalog.we-online.de/em/datasheet/9774040960.pdf, h: 4 9774050960: datasheet: https://katalog.we-online.de/em/datasheet/9774050960.pdf, h: 5 9774060960: datasheet: https://katalog.we-online.de/em/datasheet/9774060960.pdf, h: 6 9774070960: datasheet: https://katalog.we-online.de/em/datasheet/9774070960.pdf, h: 7 9774080960: datasheet: https://katalog.we-online.de/em/datasheet/9774080960.pdf, h: 8 9774090960: datasheet: https://katalog.we-online.de/em/datasheet/9774090960.pdf, h: 9 9774100960: datasheet: https://katalog.we-online.de/em/datasheet/9774100960.pdf, h: 10 9774110960: datasheet: https://katalog.we-online.de/em/datasheet/9774110960.pdf, h: 11 9774120960: datasheet: https://katalog.we-online.de/em/datasheet/9774120960.pdf, h: 12 9774130960: datasheet: https://katalog.we-online.de/em/datasheet/9774130960.pdf, h: 13 9774140960: datasheet: https://katalog.we-online.de/em/datasheet/9774140960.pdf, h: 14 9774150960: datasheet: https://katalog.we-online.de/em/datasheet/9774150960.pdf, h: 15 4.5mm: series_prefix: WA-SMST footprint: ring: id: 5.4 od: 9.4 paste: clearance: 0.8 id: 5.48 od: 9.27 npth: 5.4 mechanical: id: 4.5 od: 8.2 od1: 5.2 h1: 1.4 parts: 9774010982: datasheet: https://katalog.we-online.de/em/datasheet/9774010982.pdf h: 1 9774020982: datasheet: https://katalog.we-online.de/em/datasheet/9774020982.pdf h: 2 9774030982: datasheet: https://katalog.we-online.de/em/datasheet/9774030982.pdf h: 3 9774040982: datasheet: https://katalog.we-online.de/em/datasheet/9774040982.pdf h: 4 9774050982: datasheet: https://katalog.we-online.de/em/datasheet/9774050982.pdf h: 5 9774060982: datasheet: https://katalog.we-online.de/em/datasheet/9774060982.pdf h: 6 9774070982: datasheet: https://katalog.we-online.de/em/datasheet/9774070982.pdf h: 7 9774080982: datasheet: https://katalog.we-online.de/em/datasheet/9774080982.pdf h: 8 9774090982: datasheet: https://katalog.we-online.de/em/datasheet/9774090982.pdf h: 9 9774100982: datasheet: https://katalog.we-online.de/em/datasheet/9774100982.pdf h: 10 M1.6: series_prefix: WA-SMSI footprint: ring: id: 2.1 od: 4 paste: clearance: 0.4 id: 2.2 od: 3.8 npth: 2.1 mechanical: id: M1.6 od: 3.3 od1: 1.9 h1: 0.7 parts: 9774010633: datasheet: https://katalog.we-online.com/em/datasheet/9774010633.pdf h: 1 9774015633: datasheet: https://katalog.we-online.com/em/datasheet/9774015633.pdf h: 1.5 9774020633: datasheet: https://katalog.we-online.com/em/datasheet/9774020633.pdf h: 2 9774025633: datasheet: https://katalog.we-online.com/em/datasheet/9774025633.pdf h: 2.5 9774030633: datasheet: https://katalog.we-online.com/em/datasheet/9774030633.pdf h: 3 97730356334: datasheet: https://katalog.we-online.com/em/datasheet/97730356334.pdf h: 3.5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730406334: datasheet: https://katalog.we-online.com/em/datasheet/97730406334.pdf h: 4 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730456334: datasheet: https://katalog.we-online.com/em/datasheet/97730456334.pdf h: 4.5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730506334: datasheet: https://katalog.we-online.com/em/datasheet/97730506334.pdf h: 5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730606334: datasheet: https://katalog.we-online.com/em/datasheet/97730606334.pdf h: 6 thread_depth: 2 drill_depth: 3.13 # from 3d model M1.6_s: series_prefix: WA-SMSI footprint: ring: id: 1 od: 4 paste: paste_count: 2 clearance: 1.1 id: 1.2 od: 3.8 npth: 1 mechanical: id: M1.6 od: 3.3 od1: 0.8 h1: 0.5 parts: 97730256332: datasheet: https://katalog.we-online.com/em/datasheet/97730256332.pdf h: 2.5 thread_depth: 1.5 drill_depth: 1.63 # from 3d model 97730306332: datasheet: https://katalog.we-online.com/em/datasheet/97730306332.pdf h: 3 thread_depth: 1.8 drill_depth: 1.93 # from 3d model 97730356332: datasheet: https://katalog.we-online.com/em/datasheet/97730356332.pdf h: 3.5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730406332: datasheet: https://katalog.we-online.com/em/datasheet/97730406332.pdf h: 4 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730456332: datasheet: https://katalog.we-online.com/em/datasheet/97730456332.pdf h: 4.5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730506332: datasheet: https://katalog.we-online.com/em/datasheet/97730506332.pdf h: 5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730606332: datasheet: https://katalog.we-online.com/em/datasheet/97730606332.pdf h: 6 thread_depth: 2 drill_depth: 3.13 # from 3d model M1.6_smt: series_prefix: WA-SMSI suffix: NoNPTH footprint: ring: id: 0 od: 4 paste: clearance: 0.3 id: 0.6 # 2*clearance to ensure proper handling (would need to implement a segment instead of an arc to really handle this. Too much work for now.) od: 3.8 mechanical: id: M1.6 od: 3.3 parts: 97730256330: datasheet: https://katalog.we-online.com/em/datasheet/97730256330R.pdf h: 2.5 thread_depth: 1.5 drill_depth: 1.63 # from 3d model 97730306330: datasheet: https://katalog.we-online.com/em/datasheet/97730306330.pdf h: 3 thread_depth: 1.8 drill_depth: 1.93 # from 3d model 97730356330: datasheet: https://katalog.we-online.com/em/datasheet/97730356330.pdf h: 3.5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730406330: datasheet: https://katalog.we-online.com/em/datasheet/97730406330.pdf h: 4 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730456330: datasheet: https://katalog.we-online.com/em/datasheet/97730456330.pdf h: 4.5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730506330: datasheet: https://katalog.we-online.com/em/datasheet/97730506330.pdf h: 5 thread_depth: 2 drill_depth: 3.13 # from 3d model 97730606330: datasheet: https://katalog.we-online.com/em/datasheet/97730606330.pdf h: 6 thread_depth: 2 drill_depth: 3.13 # from 3d model M2: series_prefix: WA-SMSI footprint: ring: id: 3 od: 5.3 paste: # from 2.25mm ID version (Has same mechanical dimensions) clearance: 0.6 id: 3.1 od: 5.12 npth: 3 mechanical: id: M2 od: 4.35 od1: 2.8 h1: 1.4 parts: 9774010243: datasheet: https://katalog.we-online.de/em/datasheet/9774010243.pdf h: 1 9774015243: datasheet: https://katalog.we-online.de/em/datasheet/9774015243.pdf h: 1.5 9774020243: datasheet: https://katalog.we-online.de/em/datasheet/9774020243.pdf h: 2 9774025243: datasheet: https://katalog.we-online.de/em/datasheet/9774025243.pdf h: 2.5 9774030243: datasheet: https://katalog.we-online.de/em/datasheet/9774030243.pdf h: 3 9774035243: datasheet: https://katalog.we-online.de/em/datasheet/9774035243.pdf h: 3.5 9774040243: datasheet: https://katalog.we-online.de/em/datasheet/9774040243.pdf h: 4 9774045243: datasheet: https://katalog.we-online.de/em/datasheet/9774045243.pdf h: 4.5 9774050243: datasheet: https://katalog.we-online.de/em/datasheet/9774050243.pdf h: 5 9774060243: datasheet: https://katalog.we-online.de/em/datasheet/9774060243.pdf h: 6 9774070243: datasheet: https://katalog.we-online.de/em/datasheet/9774070243.pdf h: 7 9774080243: datasheet: https://katalog.we-online.de/em/datasheet/9774080243.pdf h: 8 M3: series_prefix: WA-SMSI footprint: ring: id: 4.4 od: 7.4 paste: # measured from eagle footprint (not dimensioned in datasheet) clearance: 0.5 id: 4.72 od: 6.92 npth: 4.4 mechanical: id: M3 od: 6 od1: 4.2 h1: 1.4 parts: 9774010360: datasheet: https://katalog.we-online.de/em/datasheet/9774010360.pdf h: 1 9774015360: datasheet: https://katalog.we-online.de/em/datasheet/9774015360.pdf h: 1.5 9774020360: datasheet: https://katalog.we-online.de/em/datasheet/9774020360.pdf h: 2 9774025360: datasheet: https://katalog.we-online.de/em/datasheet/9774025360.pdf h: 2.5 9774030360: datasheet: https://katalog.we-online.de/em/datasheet/9774030360R.pdf h: 3 9774040360: datasheet: https://katalog.we-online.de/em/datasheet/9774040360.pdf h: 4 9774050360: datasheet: https://katalog.we-online.de/em/datasheet/9774050360.pdf h: 5 9774060360: datasheet: https://katalog.we-online.de/em/datasheet/9774060360.pdf h: 6 9774070360: datasheet: https://katalog.we-online.de/em/datasheet/9774070360.pdf h: 7 9774080360: datasheet: https://katalog.we-online.de/em/datasheet/9774080360.pdf h: 8 9774090360: datasheet: https://katalog.we-online.de/em/datasheet/9774090360.pdf h: 9 9774100360: datasheet: https://katalog.we-online.de/em/datasheet/9774100360.pdf h: 10 9774110360: datasheet: https://katalog.we-online.de/em/datasheet/9774110360.pdf h: 11 9774120360: datasheet: https://katalog.we-online.de/em/datasheet/9774120360.pdf h: 12 9774130360: datasheet: https://katalog.we-online.de/em/datasheet/9774130360.pdf h: 13 9774140360: datasheet: https://katalog.we-online.de/em/datasheet/9774140360.pdf h: 14 9774150360: datasheet: https://katalog.we-online.de/em/datasheet/9774150360.pdf h: 15 M4: series_prefix: WA-SMSI footprint: ring: id: 5.4 od: 9.4 paste: clearance: 0.8 id: 5.48 od: 9.27 npth: 5.4 mechanical: id: 4.5 od: 8.2 od1: 5.2 h1: 1.4 parts: 9774010482: datasheet: https://katalog.we-online.de/em/datasheet/9774010482.pdf h: 1 9774020482: datasheet: https://katalog.we-online.de/em/datasheet/9774020482.pdf h: 2 9774030482: datasheet: https://katalog.we-online.de/em/datasheet/9774030482.pdf h: 3 9774040482: datasheet: https://katalog.we-online.de/em/datasheet/9774040482.pdf h: 4 9774050482: datasheet: https://katalog.we-online.de/em/datasheet/9774050482.pdf h: 5 9774060482: datasheet: https://katalog.we-online.de/em/datasheet/9774060482.pdf h: 6 9774070482: datasheet: https://katalog.we-online.de/em/datasheet/9774070482.pdf h: 7 9774080482: datasheet: https://katalog.we-online.de/em/datasheet/9774080482.pdf h: 8 9774090482: datasheet: https://katalog.we-online.de/em/datasheet/9774090482.pdf h: 9 9774100482: datasheet: https://katalog.we-online.de/em/datasheet/9774100482.pdf h: 10 3.2R: series_prefix: WA-SMSR suffix: ReverseMount footprint: ring: id: 4.5 od: 7.4 paste: clearance: 0.8 id: 4.58 od: 7.27 npth: 4.4 mechanical: id: 3.2 od: 6 od1: 4.2 h: 1 parts: 9775026960: datasheet: https://katalog.we-online.com/em/datasheet/9775026960R.pdf h1: 2.6 9775031960: datasheet: https://katalog.we-online.com/em/datasheet/9775031960.pdf h1: 3.1 9775036960: datasheet: https://katalog.we-online.com/em/datasheet/9775036960.pdf h1: 3.6 9775041960: datasheet: https://katalog.we-online.com/em/datasheet/9775041960.pdf h1: 4.1 9775046960: datasheet: https://katalog.we-online.com/em/datasheet/9775046960.pdf h1: 4.6 9775051960: datasheet: https://katalog.we-online.com/em/datasheet/9775051960.pdf h1: 5.1 9775056960: datasheet: https://katalog.we-online.com/em/datasheet/9775056960.pdf h1: 5.6 9775066960: datasheet: https://katalog.we-online.com/em/datasheet/9775066960.pdf h1: 6.6 9775076960: datasheet: https://katalog.we-online.com/em/datasheet/9775076960.pdf h1: 7.6 9775086960: datasheet: https://katalog.we-online.com/em/datasheet/9775086960.pdf h1: 8.6 9775096960: datasheet: https://katalog.we-online.com/em/datasheet/9775096960.pdf h1: 9.6 9775106960: datasheet: https://katalog.we-online.com/em/datasheet/9775106960.pdf h1: 10.6 9775116960: datasheet: https://katalog.we-online.com/em/datasheet/9775116960.pdf h1: 11.6 M3R: series_prefix: WA-SMSR suffix: ReverseMount footprint: ring: id: 4.5 od: 7.4 paste: clearance: 0.8 id: 4.58 od: 7.27 npth: 4.4 mechanical: id: M3 od: 6 od1: 4.2 h: 1 parts: 9775026360: datasheet: https://katalog.we-online.com/em/datasheet/9775026360.pdf h1: 2.6 9775031360: datasheet: https://katalog.we-online.com/em/datasheet/9775031360.pdf h1: 3.1 9775036360: datasheet: https://katalog.we-online.com/em/datasheet/9775036360.pdf h1: 3.6 9775041360: datasheet: https://katalog.we-online.com/em/datasheet/9775041360.pdf h1: 4.1 9775046360: datasheet: https://katalog.we-online.com/em/datasheet/9775046360.pdf h1: 4.6 9775051360: datasheet: https://katalog.we-online.com/em/datasheet/9775051360.pdf h1: 5.1 9775056360: datasheet: https://katalog.we-online.com/em/datasheet/9775056360.pdf h1: 5.6 9775066360: datasheet: https://katalog.we-online.com/em/datasheet/9775066360.pdf h1: 6.6 9775076360: datasheet: https://katalog.we-online.com/em/datasheet/9775076360.pdf h1: 7.6 9775086360: datasheet: https://katalog.we-online.com/em/datasheet/9775086360.pdf h1: 8.6 9775096360: datasheet: https://katalog.we-online.com/em/datasheet/9775096360.pdf h1: 9.6 9775106360: datasheet: https://katalog.we-online.com/em/datasheet/9775106360.pdf h1: 10.6 9775116360: datasheet: https://katalog.we-online.com/em/datasheet/9775116360.pdf h1: 11.6 snap: series_prefix: WA-SMSSR suffix: SnapRivet footprint: ring: id: 4.4 od: 7.4 paste: clearance: 0.8 id: 4.48 od: 7.27 npth: 4.4 mechanical: id: 3.3 id1: 2.15 t1: 0.5 od: 6 od1: 4.2 h1: 1.4 parts: 9776100960: datasheet: https://katalog.we-online.com/em/datasheet/9776100960R.pdf h: 10 9776020960: datasheet: https://katalog.we-online.com/em/datasheet/9776020960.pdf h: 2 9776025960: datasheet: https://katalog.we-online.com/em/datasheet/9776025960.pdf h: 2.5 9776030960: datasheet: https://katalog.we-online.com/em/datasheet/9776030960.pdf h: 3 9776040960: datasheet: https://katalog.we-online.com/em/datasheet/9776040960.pdf h: 4 9776050960: datasheet: https://katalog.we-online.com/em/datasheet/9776050960.pdf h: 5 9776060960: datasheet: https://katalog.we-online.com/em/datasheet/9776060960.pdf h: 6 9776070960: datasheet: https://katalog.we-online.com/em/datasheet/9776070960.pdf h: 7 9776080960: datasheet: https://katalog.we-online.com/em/datasheet/9776080960.pdf h: 8 9776090960: datasheet: https://katalog.we-online.com/em/datasheet/9776090960.pdf h: 9 external_m3: series_prefix: WA-SMSE footprint: ring: id: 1 od: 7.4 paste: paste_count: 2 clearance: 1.06 id: 1.2 od: 7.2 npth: 1 mechanical: ext_thread: od: M3 L: 6 undercut: od: 2.2 L: [0.5, 1.25] r: 0.2 od: 6 od1: 0.8 h1: 0.5 parts: 9771050360: datasheet: https://katalog.we-online.com/em/datasheet/9771050360.pdf h: 5 9771060360: datasheet: https://katalog.we-online.com/em/datasheet/9771060360.pdf h: 6 9771070360: datasheet: https://katalog.we-online.com/em/datasheet/9771070360.pdf h: 7 9771080360: datasheet: https://katalog.we-online.com/em/datasheet/9771080360.pdf h: 8 9771090360: datasheet: https://katalog.we-online.com/em/datasheet/9771090360.pdf h: 9 9771100360: datasheet: https://katalog.we-online.com/em/datasheet/9771100360.pdf h: 10 9771110360: datasheet: https://katalog.we-online.com/em/datasheet/9771110360.pdf h: 11 9771120360: datasheet: https://katalog.we-online.com/em/datasheet/9771120360.pdf h: 12 9771130360: datasheet: https://katalog.we-online.com/em/datasheet/9771130360.pdf h: 13 9771140360: datasheet: https://katalog.we-online.com/em/datasheet/9771140360.pdf h: 14 9771150360: datasheet: https://katalog.we-online.com/em/datasheet/9771150360.pdf h: 15 ================================================ FILE: scripts/Mounting_Holes/mounting_hole_long.yaml ================================================ MountingHole_5.3x7.3mm_M5_Pad_Via: description: "Mounting Hole 5.3x7.3mm, M5, including vias" courtjard: 0.25 hole_x: 7.3 hole_y: 5.3 anular_ring: 2 via: True via_diameter: 0.6 via_count: 16 ================================================ FILE: scripts/Multicomp/connectors_multicomp_mc9a12.py ================================================ #!/usr/bin/env python import sys sys.path.append("../../kicad_mod") # load kicad_mod path import argparse from kicad_mod import KicadMod, createNumberedPadsTHT parser = argparse.ArgumentParser() parser.add_argument('pincount', help='number of pins of the jst connector', type=int, nargs=1) parser.add_argument('-v', '--verbose', help='show extra information while generating the footprint', action='store_true') #TODO args = parser.parse_args() # http://www.farnell.com/datasheets/1520732.pdf pincount = int(args.pincount[0]) pad_spacing = 2.54 start_pos_x = 0 end_pos_x = pad_spacing*(pincount-2)/2 # Through-hole type shrouded header, Top entry type footprint_name = 'Multicomp_MC9A12-{pincount:02g}34_2x{pincount_half:02g}x2.54mm_Straight'.format(pincount=pincount, pincount_half=pincount/2) # TODO: name kicad_mod = KicadMod(footprint_name) kicad_mod.setDescription('http://www.farnell.com/datasheets/1520732.pdf') kicad_mod.setTags('connector multicomp MC9A MC9A12') # set general values kicad_mod.addText('reference', 'REF**', {'x':start_pos_x-3, 'y':-7}, 'F.SilkS') kicad_mod.addText('value', footprint_name, {'x':end_pos_x/2., 'y':5}, 'F.Fab') # create Silkscreen # outline kicad_mod.addRectLine({'x':start_pos_x-3.87-1.2, 'y':3.2}, {'x':end_pos_x+3.87+1.2, 'y':-pad_spacing-3.2}, 'F.SilkS', 0.15) # slot(s) if pincount < 60: kicad_mod.addPolygoneLine([{'x':((start_pos_x+end_pos_x)/2)-4.45/2, 'y':3.2} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2, 'y':1.9} ,{'x':start_pos_x-3.87, 'y':1.9} ,{'x':start_pos_x-3.87, 'y':-pad_spacing-1.9} ,{'x':end_pos_x+3.87, 'y':-pad_spacing-1.9} ,{'x':end_pos_x+3.87, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2, 'y':3.2}], 'F.SilkS', 0.15) else: kicad_mod.addPolygoneLine([{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3-4.1, 'y':3.2} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3-4.1, 'y':1.9} ,{'x':start_pos_x-3.87, 'y':1.9} ,{'x':start_pos_x-3.87, 'y':-pad_spacing-1.9} ,{'x':end_pos_x+3.87, 'y':-pad_spacing-1.9} ,{'x':end_pos_x+3.87, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3+4.1, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3+4.1, 'y':3.2}], 'F.SilkS', 0.15) kicad_mod.addPolygoneLine([{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3, 'y':3.2} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2, 'y':3.2}], 'F.SilkS', 0.15) kicad_mod.addPolygoneLine([{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3, 'y':3.2} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2, 'y':1.9} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2, 'y':3.2}], 'F.SilkS', 0.15) # lines above the footprint kicad_mod.addPolygoneLine([{'x':end_pos_x/2-0.25, 'y':-pad_spacing-3.2} ,{'x':end_pos_x/2-0.25, 'y':-pad_spacing-3.2-0.2} ,{'x':end_pos_x/2+0.25, 'y':-pad_spacing-3.2-0.2} ,{'x':end_pos_x/2+0.25, 'y':-pad_spacing-3.2}], 'F.SilkS', 0.15) kicad_mod.addLine({'x':end_pos_x/2-0.25, 'y':-pad_spacing-3.2-0.1}, {'x':end_pos_x/2+0.25, 'y':-pad_spacing-3.2-0.1}, 'F.SilkS', 0.15) kicad_mod.addPolygoneLine([{'x':end_pos_x+2.4-0.25, 'y':-pad_spacing-3.2} ,{'x':end_pos_x+2.4-0.25, 'y':-pad_spacing-3.2-0.2} ,{'x':end_pos_x+2.4+0.25, 'y':-pad_spacing-3.2-0.2} ,{'x':end_pos_x+2.4+0.25, 'y':-pad_spacing-3.2}], 'F.SilkS', 0.15) kicad_mod.addLine({'x':end_pos_x+2.4-0.25, 'y':-pad_spacing-3.2-0.1}, {'x':end_pos_x+2.4+0.25, 'y':-pad_spacing-3.2-0.1}, 'F.SilkS', 0.15) kicad_mod.addPolygoneLine([{'x':start_pos_x-2.4-0.25, 'y':-pad_spacing-3.2} ,{'x':start_pos_x-2.4-0.25, 'y':-pad_spacing-3.2-0.2} ,{'x':start_pos_x-2.4+0.25, 'y':-pad_spacing-3.2-0.2} ,{'x':start_pos_x-2.4+0.25, 'y':-pad_spacing-3.2}], 'F.SilkS', 0.15) kicad_mod.addLine({'x':start_pos_x-2.4-0.25, 'y':-pad_spacing-3.2-0.1}, {'x':start_pos_x-2.4+0.25, 'y':-pad_spacing-3.2-0.1}, 'F.SilkS', 0.15) # triangle which is pointing at 1 kicad_mod.addPolygoneLine([{'x':start_pos_x-2.2, 'y':0.6} ,{'x':start_pos_x-2.2, 'y':-0.6} ,{'x':start_pos_x-1.6, 'y':0} ,{'x':start_pos_x-2.2, 'y':0.6}], 'F.SilkS', 0.15) # create Courtyard def round_to(n, precision): correction = 0.5 if n >= 0 else -0.5 return int( n/precision+correction ) * precision kicad_mod.addRectLine({'x':round_to(start_pos_x-3.87-1.2-0.5,0.05), 'y':3.2+0.5}, {'x':round_to(end_pos_x+3.87+1.2+0.5,0.05), 'y':round_to(-pad_spacing-3.2-0.5,0.05)}, 'F.CrtYd', 0.05) # create pads pad_diameter = 1 pad_size = {'x':1.7, 'y':1.7} for pad_number in range(1, pincount, 2): pad_pos_x = (pad_number-1)/2*pad_spacing if pad_number == 1: kicad_mod.addPad(pad_number, 'thru_hole', 'rect', {'x':pad_pos_x, 'y':0}, pad_size, pad_diameter, ['*.Cu', '*.Mask', 'F.SilkS']) else: kicad_mod.addPad(pad_number, 'thru_hole', 'circle', {'x':pad_pos_x, 'y':0}, pad_size, pad_diameter, ['*.Cu', '*.Mask', 'F.SilkS']) kicad_mod.addPad(pad_number+1, 'thru_hole', 'circle', {'x':pad_pos_x, 'y':-pad_spacing}, pad_size, pad_diameter, ['*.Cu', '*.Mask', 'F.SilkS']) # output kicad model print(kicad_mod) ================================================ FILE: scripts/Multicomp/connectors_multicomp_mc9a22.py ================================================ #!/usr/bin/env python import sys sys.path.append("../../kicad_mod") # load kicad_mod path import argparse from kicad_mod import KicadMod, createNumberedPadsTHT parser = argparse.ArgumentParser() parser.add_argument('pincount', help='number of pins of the jst connector', type=int, nargs=1) parser.add_argument('-v', '--verbose', help='show extra information while generating the footprint', action='store_true') #TODO args = parser.parse_args() # http://www.farnell.com/cad/360651.pdf pincount = int(args.pincount[0]) pad_spacing = 2.54 start_pos_x = 0 end_pos_x = pad_spacing*(pincount-2)/2 # Through-hole type shrouded header, Top entry type footprint_name = "Multicomp_MC9A22-{pincount:02g}34_2x{pincount_half:02g}x2.54mm_Angled".format(pincount=pincount, pincount_half=pincount/2) kicad_mod = KicadMod(footprint_name) kicad_mod.setDescription('http://www.farnell.com/cad/360651.pdf') kicad_mod.setTags('connector multicomp MC9A MC9A22') # set general values kicad_mod.addText('reference', 'REF**', {'x':start_pos_x-3, 'y':-15}, 'F.SilkS') kicad_mod.addText('value', footprint_name, {'x':end_pos_x/2., 'y':-5.5}, 'F.Fab') # create Silkscreen # outline kicad_mod.addRectLine({'x':start_pos_x-3.87-1.2, 'y':-pad_spacing-1.8}, {'x':end_pos_x+3.87+1.2, 'y':-pad_spacing-1.8-8.9}, 'F.SilkS', 0.15) # slot(s) def draw_pin_silk(slot_pin_x): kicad_mod.addPolygoneLine([{'x':slot_pin_x-0.4, 'y':-pad_spacing-1.8-8.9+6.6} ,{'x':slot_pin_x-0.4, 'y':-pad_spacing-1.8-8.5} ,{'x':slot_pin_x-0.2, 'y':-pad_spacing-1.8-8.7} ,{'x':slot_pin_x+0.2, 'y':-pad_spacing-1.8-8.7} ,{'x':slot_pin_x+0.4, 'y':-pad_spacing-1.8-8.5} ,{'x':slot_pin_x+0.4, 'y':-pad_spacing-1.8-8.9+6.6}], 'F.SilkS', 0.15) kicad_mod.addPolygoneLine([{'x':((start_pos_x+end_pos_x)/2)-4.45/2, 'y':-pad_spacing-1.8-8.9} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2, 'y':-pad_spacing-1.8-8.9+6.6} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2, 'y':-pad_spacing-1.8-8.9+6.6} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2, 'y':-pad_spacing-1.8-8.9}], 'F.SilkS', 0.15) if pincount%4 != 0: slot_pin_x = start_pos_x+((int)(pincount/4)*pad_spacing) draw_pin_silk(slot_pin_x) else: slot_pin_x = start_pos_x+((int)(pincount/4-1)*pad_spacing) draw_pin_silk(slot_pin_x) slot_pin_x = start_pos_x+((int)(pincount/4)*pad_spacing) draw_pin_silk(slot_pin_x) if pincount >= 60: slot_pin_x = start_pos_x+((int)(pincount/4-1-4)*pad_spacing) draw_pin_silk(slot_pin_x) slot_pin_x = start_pos_x+((int)(pincount/4+4)*pad_spacing) draw_pin_silk(slot_pin_x) if pincount >= 60: kicad_mod.addPolygoneLine([{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3, 'y':-pad_spacing-1.8-8.9} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3, 'y':-pad_spacing-1.8-8.9+6.6} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3-4.1, 'y':-pad_spacing-1.8-8.9+6.6} ,{'x':((start_pos_x+end_pos_x)/2)-4.45/2-7.3-4.1, 'y':-pad_spacing-1.8-8.9}], 'F.SilkS', 0.15) kicad_mod.addPolygoneLine([{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3, 'y':-pad_spacing-1.8-8.9} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3, 'y':-pad_spacing-1.8-8.9+6.6} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3+4.1, 'y':-pad_spacing-1.8-8.9+6.6} ,{'x':((start_pos_x+end_pos_x)/2)+4.45/2+7.3+4.1, 'y':-pad_spacing-1.8-8.9}], 'F.SilkS', 0.15) # triangle which is pointing at 1 kicad_mod.addPolygoneLine([{'x':start_pos_x-1, 'y':-12.5} ,{'x':start_pos_x+1, 'y':-12.5} ,{'x':start_pos_x, 'y':-11} ,{'x':start_pos_x-1, 'y':-12.5}], 'F.SilkS', 0.15) # create Courtyard def round_to(n, precision): correction = 0.5 if n >= 0 else -0.5 return int( n/precision+correction ) * precision kicad_mod.addRectLine({'x':round_to(start_pos_x-3.87-1.2-0.5,0.05), 'y':1.7/2+0.5}, {'x':round_to(end_pos_x+3.87+1.2+0.5,0.05), 'y':round_to(-pad_spacing-1.8-8.9-0.5,0.05)}, 'F.CrtYd', 0.05) # create pads pad_diameter = 1 pad_size = {'x':1.7, 'y':1.7} for pad_number in range(1, pincount, 2): pad_pos_x = (pad_number-1)/2*pad_spacing if pad_number == 1: kicad_mod.addPad(pad_number, 'thru_hole', 'rect', {'x':pad_pos_x, 'y':0}, pad_size, pad_diameter, ['*.Cu', '*.Mask', 'F.SilkS']) else: kicad_mod.addPad(pad_number, 'thru_hole', 'circle', {'x':pad_pos_x, 'y':0}, pad_size, pad_diameter, ['*.Cu', '*.Mask', 'F.SilkS']) kicad_mod.addPad(pad_number+1, 'thru_hole', 'circle', {'x':pad_pos_x, 'y':-pad_spacing}, pad_size, pad_diameter, ['*.Cu', '*.Mask', 'F.SilkS']) kicad_mod.addLine({'x':pad_pos_x-0.4, 'y':-1.1}, {'x':pad_pos_x-0.4, 'y':-pad_spacing+1.1}, 'F.SilkS', 0.15) kicad_mod.addLine({'x':pad_pos_x+0.4, 'y':-1.1}, {'x':pad_pos_x+0.4, 'y':-pad_spacing+1.1}, 'F.SilkS', 0.15) kicad_mod.addLine({'x':pad_pos_x-0.4, 'y':-pad_spacing-1.1}, {'x':pad_pos_x-0.4, 'y':-pad_spacing-1.8}, 'F.SilkS', 0.15) kicad_mod.addLine({'x':pad_pos_x+0.4, 'y':-pad_spacing-1.1}, {'x':pad_pos_x+0.4, 'y':-pad_spacing-1.8}, 'F.SilkS', 0.15) # output kicad model print(kicad_mod) ================================================ FILE: scripts/Multicomp/create_connectors_multicomp.sh ================================================ #!/bin/bash mkdir Connectors_Multicomp.pretty # Wire-To-Board-Steckverbinder, Straight for i in "10" "14" "16" "20" "26" "34" "40" "50" "60" "64" do i_2=$((i/2)) if [ $i_2 -lt 10 ] then PIN_NUMBER="0${i_2}" else PIN_NUMBER=${i_2} fi ./connectors_multicomp_mc9a12.py $i > "Connectors_Multicomp.pretty/Multicomp_MC9A12-${i}34_2x${PIN_NUMBER}x2.54mm_Straight.kicad_mod" done # Wire-To-Board-Steckverbinder, Right Angle for i in "10" "14" "16" "20" "26" "34" "40" "50" "60" do i_2=$((i/2)) if [ $i_2 -lt 10 ] then PIN_NUMBER="0${i_2}" else PIN_NUMBER=${i_2} fi ./connectors_multicomp_mc9a22.py $i > "Connectors_Multicomp.pretty/Multicomp_MC9A22-${i}34_2x${PIN_NUMBER}x2.54mm_Angled.kicad_mod" done ================================================ FILE: scripts/Oscillators_SMD/make_oscillators.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_crystals import * if __name__ == '__main__': standardtags="SMD SMT crystal oscillator" # common settings makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_IQD_IQXO70", addSizeFootprintName=True, pins=4, pad_sep_x=5.08, pad_sep_y=4.2, pad=[1.8,2.0], pack_width=7.5, pack_height=5, pack_bevel=0.4, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="IQD Crystal Clock Oscillator IQXO-70, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags+"", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Fordahl_DFAS15", addSizeFootprintName=True, pins=4, pad_sep_x=2.6+1.5, pad_sep_y=1.6+1.2, pad=[1.5, 1.2], pack_width=5, pack_height=3.2, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.5, description="Ultraminiature Crystal Clock Oscillator TXCO Fordahl DFA S15-OV/UOV, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Fordahl_DFAS11", addSizeFootprintName=True, pins=4, pad_sep_x=5.08, pad_sep_y=4.4, pad=[1.4,2], pack_width=7, pack_height=5, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="Miniature Crystal Clock Oscillator TXCO Fordahl DFA S11-OV/UOV, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Fordahl_DFAS2", addSizeFootprintName=True, pins=4, pad_sep_x=5.08, pad_sep_y=4.4, pad=[1.4, 2], pack_width=7.3, pack_height=5.08, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="Mminiature Crystal Clock Oscillator TXCO Fordahl DFA S2-KS/LS/US, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Fordahl_DFAS3", addSizeFootprintName=True, pins=4, pad_sep_x=5.08, pad_sep_y=6.4, pad=[1.5, 2.2], pack_width=9.1, pack_height=7.2, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="Miniature Crystal Clock Oscillator TXCO Fordahl DFA S3-KS/LS/US, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Fordahl_DFAS7", addSizeFootprintName=True, pins=4, pad_sep_x=19.0, pad_sep_y=7.6, pad=[2.6,1.3], pack_width=19.9, pack_height=12.9, pack_bevel=2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="Miniature Crystal Clock Oscillator TXCO Fordahl DFA S7-K/L, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Fordahl_DFAS7", addSizeFootprintName=True, pins=4, pad_sep_x=19.0, pad_sep_y=7.6, pad=[2.6, 1.3], pack_width=19.9, pack_height=12.9, pack_bevel=2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="Miniature Crystal Clock Oscillator TXCO Fordahl DFA S7-K/L, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystal(footprint_name="Oscillator_SMD_Fordahl_DFAS1", addSizeFootprintName=True, pins=6, pad_sep_x=2.54, pad_sep_y=8.9, pad=[1.27, 2.54], pack_width=14.8, pack_height=9.1, pack_bevel=1,style="rect1bevel", hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.5, description="Miniature Crystal Clock Oscillator TXCO Fordahl DFA S1-KHZ/LHZ, http://www.iqdfrequencyproducts.com/products/details/iqxo-70-11-30.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Abracon_ASV", addSizeFootprintName=True, pins=4, pad_sep_x=5.08, pad_sep_y=4.0, pad=[1.8, 2], pack_width=7, pack_height=5.08, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="Miniature Crystal Clock Oscillator Abracon ASV series, http://www.abracon.com/Oscillators/ASV.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_Abracon_ASE", addSizeFootprintName=True, pins=4, pad_sep_x=2.1, pad_sep_y=1.65, pad=[1.3, 1.1], pack_width=3.2, pack_height=2.5, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.5, description="Miniature Crystal Clock Oscillator Abracon ASE series, http://www.abracon.com/Oscillators/ASEseries.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_TXC_7C", addSizeFootprintName=True, pins=4, pad_sep_x=2.54, pad_sep_y=2.2, pad=[1.4, 1.2], pack_width=5, pack_height=3.2, pack_bevel=0.2, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=1, description="Miniature Crystal Clock Oscillator TXC 7C series, http://www.txccorp.com/download/products/osc/7C_o.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_EuroQuartz_XO32", addSizeFootprintName=True, pins=4, pad_sep_x=2.15, pad_sep_y=1.55, pad=[1,0.9], pack_width=3.2, pack_height=2.5, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.5, description="Miniature Crystal Clock Oscillator EuroQuartz XO32 series, http://cdn-reichelt.de/documents/datenblatt/B400/XO32.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_EuroQuartz_XO53", addSizeFootprintName=True, pins=4, pad_sep_x=2.54, pad_sep_y=2.2, pad=[1.4,1.2], pack_width=5, pack_height=3.2, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=1, description="Miniature Crystal Clock Oscillator EuroQuartz XO53 series, http://cdn-reichelt.de/documents/datenblatt/B400/XO53.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_EuroQuartz_XO91", addSizeFootprintName=True, pins=4, pad_sep_x=5, pad_sep_y=4.2, pad=[2, 2], pack_width=7, pack_height=5, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="Miniature Crystal Clock Oscillator EuroQuartz XO91 series, http://cdn-reichelt.de/documents/datenblatt/B400/XO91.pdf", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_SeikoEpson_SG8002JA", addSizeFootprintName=True, pins=4, style="dip", pad_sep_x=5.08, pad_sep_y=8.8, pad=[1.3, 3], pack_width=14, pack_height=8.65, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Oscillator Seiko Epson SG-8002JA https://support.epson.biz/td/api/doc_check.php?mode=dl&lang=en&Parts=SG-8002DC", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_SeikoEpson_SG8002JC", addSizeFootprintName=True, pins=4, style="dip", pad_sep_x=5.08, pad_sep_y=4.6, pad=[1.3, 2.1], pack_width=10.5, pack_height=5, pack_bevel=0, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Oscillator Seiko Epson SG-8002JC https://support.epson.biz/td/api/doc_check.php?mode=dl&lang=en&Parts=SG-8002DC", tags=standardtags + "", lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_SeikoEpson_SG8002CE", addSizeFootprintName=True, pins=4, pad_sep_x=2.4, pad_sep_y=1.9, pad=[1.4,1.2], pack_width=3.2, pack_height=2.5, pack_bevel=0.1, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Oscillator Seiko Epson SG-8002CE https://support.epson.biz/td/api/doc_check.php?mode=dl&lang=en&Parts=SG-8002DC", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_SeikoEpson_SG8002LB", addSizeFootprintName=True, pins=4, pad_sep_x=2.54, pad_sep_y=2.2, pad=[1.6, 1.5], pack_width=5, pack_height=3.2, pack_bevel=0.0, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=0.5, description="SMD Crystal Oscillator Seiko Epson SG-8002LB https://support.epson.biz/td/api/doc_check.php?mode=dl&lang=en&Parts=SG-8002DC", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_SeikoEpson_SG8002CA", addSizeFootprintName=True, pins=4, pad_sep_x=5.08, pad_sep_y=4.2, pad=[1.8, 2], pack_width=7, pack_height=5, pack_bevel=0.0, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="SMD Crystal Oscillator Seiko Epson SG-8002CA https://support.epson.biz/td/api/doc_check.php?mode=dl&lang=en&Parts=SG-8002DC", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) makeSMDCrystalAndHand(footprint_name="Oscillator_SMD_SeikoEpson_SG210", addSizeFootprintName=True, pins=4, pad_sep_x=1.7, pad_sep_y=1.3, pad=[1.1,0.9], pack_width=2.5, pack_height=2, pack_bevel=0.0, hasAdhesive=True, adhesivePos=[0, 0], adhesiveSize=2, description="SMD Crystal Oscillator Seiko Epson SG-210 https://support.epson.biz/td/api/doc_check.php?mode=dl&lang=en&Parts=SG-210SED", tags=standardtags + "", lib_name="Oscillators", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]) ================================================ FILE: scripts/Packages/Package_BGA/bga.yaml ================================================ BGA-624_21.0x21.0mm_Layout25x25_P0.8mm: description: "BGA-624" size_source: "https://www.nxp.com/docs/en/package-information/SOT1529-1.pdf" body_size_x: 21.0 body_size_y: 21.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.0625 layout_x: 25 layout_y: 25 row_skips: [[1], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] LFBGA-100_10x10mm_Layout10x10_P0.8mm: description: "LFBGA-100" size_source: "http://www.st.com/resource/en/datasheet/stm32f103tb.pdf#page=87" body_size_x: 10.0 body_size_y: 10.0 pitch: 0.8 pad_diameter: 0.5 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 10 layout_y: 10 LFBGA-144_10x10mm_Layout12x12_P0.8mm: description: "LFBGA-144" size_source: "http://www.st.com/resource/en/datasheet/stm32f103ze.pdf#page=114" body_size_x: 10.0 body_size_y: 10.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 12 layout_y: 12 Texas_DSBGA-28_1.9x3.0mm_Layout4x7_P0.4mm: description: "Texas Instruments, DSBGA, area grid" size_source: "http://www.ti.com/lit/ds/symlink/bq51050b.pdf, http://www.ti.com/lit/an/snva009ag/snva009ag.pdf" body_size_x: 1.9 body_size_y: 3.0 overall_height: 0.625 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.05 layout_x: 4 layout_y: 7 Texas_DSBGA-49_3.33x3.488mm_Layout7x7_P0.4mm: description: "Texas Instruments, DSBGA, area grid" size_source: "http://www.ti.com/lit/ds/symlink/msp430f2234.pdf, http://www.ti.com/lit/an/snva009ag/snva009ag.pdf" body_size_x: 3.33 body_size_y: 3.488 overall_height: 0.625 pitch: 0.4 pad_diameter: 0.225 layout_x: 7 layout_y: 7 mask_margin: 0.05 Texas_DSBGA-64_3.415x3.535mm_Layout8x8_P0.4mm: description: "Texas Instruments, DSBGA, area grid" size_source: "http://www.ti.com/lit/ds/slas718g/slas718g.pdf, http://www.ti.com/lit/an/snva009ag/snva009ag.pdf" body_size_x: 3.415 body_size_y: 3.535 overall_height: 0.625 pitch: 0.4 pad_diameter: 0.225 layout_x: 8 layout_y: 8 mask_margin: 0.05 Texas_DSBGA-8_1.5195x1.5195mm_Layout3x3_P0.5mm: description: "Texas Instruments, DSBGA, area grid, YZR pad definition" size_source: "http://www.ti.com/lit/ml/mxbg270/mxbg270.pdf" body_size_x: 1.5195 body_size_y: 1.5195 overall_height: 0.6 pitch: 0.5 pad_diameter: 0.2625 layout_x: 3 layout_y: 3 mask_margin: 0.05 row_skips: [[], [2], []] Texas_MicroStar_Junior_BGA-113_7.0x7.0mm_Layout12x12_P0.5mm: description: "Texas Instruments, BGA Microstar Junior" size_source: "http://www.ti.com/lit/ml/mpbg674/mpbg674.pdf, http://www.ti.com/lit/wp/ssyz015b/ssyz015b.pdf" body_size_x: 7 body_size_y: 7 pitch: 0.5 pad_diameter: 0.25 layout_x: 12 layout_y: 12 mask_margin: 0.025 row_skips: [[], [], [[4, 11]], [3, 10], [3, 10], [3, 6, 7, 10], [3, 6, 7, 10], [3, 10], [3, 10], [[3, 11]], [], []] TFBGA-64_5x5mm_Layout8x8_P0.5mm: description: "TFBGA-64" size_source: "http://www.st.com/resource/en/datasheet/stm32f100v8.pdf#page=83" body_size_x: 5.0 body_size_y: 5.0 pitch: 0.5 pad_diameter: 0.28 mask_margin: 0.045 paste_margin: 0.000001 layout_x: 8 layout_y: 8 TFBGA-100_8x8mm_Layout10x10_P0.8mm: description: "TFBGA-100" size_source: "http://www.st.com/resource/en/datasheet/stm32f746zg.pdf#page=199" body_size_x: 8.0 body_size_y: 8.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 10 layout_y: 10 TFBGA-121_10x10mm_Layout11x11_P0.8mm: description: "TFBGA-121" size_source: "http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#p495" body_size_x: 10.0 body_size_y: 10.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 11 layout_y: 11 Microchip_TFBGA-196_11x11mm_Layout14x14_P0.75mm_SMD: description: "TFBGA-196" size_source: "http://ww1.microchip.com/downloads/en/DeviceDoc/SAMA5D2-Series-Data-Sheet-DS60001476C.pdf#page=2956" body_size_x: 11.0 body_size_y: 11.0 overall_height: 1.20 pitch: 0.75 pad_diameter: 0.35 mask_margin: -0.0375 paste_margin: 0.000001 layout_x: 14 layout_y: 14 TFBGA-216_13x13mm_Layout15x15_P0.8mm: description: "TFBGA-216" size_source: "http://www.st.com/resource/en/datasheet/stm32f746zg.pdf#page=219" body_size_x: 13.0 body_size_y: 13.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 15 layout_y: 15 row_skips: [[], [], [], [], [], [], [[7, 10]], [[7, 10]], [[7, 10]], [], [], [], [], [], []] TFBGA-265_14x14mm_Layout17x17_P0.8mm: description: "TFBGA-265" size_source: "http://www.st.com/resource/en/datasheet/DM00387108.pdf#page=223" body_size_x: 14.0 body_size_y: 14.0 pitch: 0.8 pad_diameter: 0.325 mask_margin: 0.0325 paste_ratio: 0.0125 layout_x: 17 layout_y: 17 row_skips: [[], [], [], [], [], [[6, 13]], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [[6, 13]], [], [], [], [], []] UCBGA-36_2.5x2.5mm_Layout6x6_P0.4mm: description: "UCBGA-36" size_source: "https://www.latticesemi.com/view_document?document_id=213" body_size_x: 2.5 body_size_y: 2.5 pitch: 0.4 pad_diameter: 0.27 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 6 layout_y: 6 UCBGA-49_3x3mm_Layout7x7_P0.4mm: description: "UCBGA-49" size_source: "https://www.latticesemi.com/view_document?document_id=213" body_size_x: 3 body_size_y: 3 pitch: 0.4 pad_diameter: 0.27 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 7 layout_y: 7 UCBGA-81_4x4mm_Layout9x9_P0.4mm: description: "UCBGA-81" size_source: "https://www.latticesemi.com/view_document?document_id=213" body_size_x: 4 body_size_y: 4 pitch: 0.4 pad_diameter: 0.27 mask_margin: 0.035 paste_margin: 0.000001 layout_x: 9 layout_y: 9 UFBGA-64_5x5mm_Layout8x8_P0.5mm: description: "UFBGA-64" size_source: "http://www.st.com/resource/en/datasheet/stm32f051t8.pdf#page=91" body_size_x: 5.0 body_size_y: 5.0 pitch: 0.5 pad_diameter: 0.28 mask_margin: 0.045 paste_margin: 0.000001 layout_x: 8 layout_y: 8 UFBGA-100_7x7mm_Layout12x12_P0.5mm: description: "UFBGA-100" size_source: "http://www.st.com/resource/en/datasheet/stm32f103tb.pdf#page=93" body_size_x: 7.0 body_size_y: 7.0 pitch: 0.5 pad_diameter: 0.28 mask_margin: 0.045 paste_margin: 0.000001 layout_x: 12 layout_y: 12 row_skips: [[], [], [6, 7], [[4, 10]], [[4, 10]], [[3, 11]], [[3, 11]], [[4, 10]], [[4, 10]], [6, 7], [], []] XBGA-121_10x10mm_Layout11x11_P0.8mm: description: "XBGA-121" size_source: "http://ww1.microchip.com/downloads/en/DeviceDoc/39969b.pdf" body_size_x: 10.0 body_size_y: 10.0 pitch: 0.8 pad_diameter: 0.32 mask_margin: 0.04 paste_margin: 0.0001 layout_x: 11 layout_y: 11 UFBGA-132_7x7mm_Layout12x12_P0.5mm: description: "UFBGA-132" size_source: "http://www.st.com/resource/en/datasheet/stm32l152zc.pdf#page=123" body_size_x: 7.0 body_size_y: 7.0 pitch: 0.5 pad_diameter: 0.27 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 12 layout_y: 12 row_skips: [[], [], [], [], [[5, 9]], [5, 8], [5, 8], [[5, 9]], [], [], [], []] UFBGA-144_7x7mm_Layout12x12_P0.5mm: description: "UFBGA-144" size_source: "http://www.st.com/resource/en/datasheet/stm32f446ze.pdf#page=186" body_size_x: 7.0 body_size_y: 7.0 pitch: 0.5 pad_diameter: 0.28 mask_margin: 0.045 paste_margin: 0.000001 layout_x: 12 layout_y: 12 UFBGA-144_10x10mm_Layout12x12_P0.8mm: description: "UFBGA-144" size_source: "http://www.st.com/resource/en/datasheet/stm32f446ze.pdf#page=189" body_size_x: 10.0 body_size_y: 10.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.075 paste_margin: 0.000001 layout_x: 12 layout_y: 12 UFBGA-169_7x7mm_Layout13x13_P0.5mm: description: "UFBGA-169" size_source: "http://www.st.com/resource/en/datasheet/stm32f429ng.pdf#page=218" body_size_x: 7.0 body_size_y: 7.0 pitch: 0.5 pad_diameter: 0.27 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 13 layout_y: 13 UFBGA-201_10x10mm_Layout15x15_P0.65mm: description: "UFBGA-201" size_source: "http://www.st.com/resource/en/datasheet/stm32f207vg.pdf#page=166" body_size_x: 10.0 body_size_y: 10.0 pitch: 0.65 pad_diameter: 0.3 mask_margin: 0.05 paste_margin: 0.000001 layout_x: 15 layout_y: 15 row_skips: [[], [], [], [], [[5, 12]], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [[5, 12]], [], [], [], []] WLP-4_0.73x0.73mm_Layout2x2_P0.35mm_Ball0.22mm_Pad0.2mm: description: "WLP-4" size_source: "https://datasheets.maximintegrated.com/en/ds/MAX40200.pdf" body_size_x: 0.728 body_size_y: 0.728 pitch: 0.35 pad_diameter: 0.2 mask_margin: 0.02 paste_margin: 0.000001 layout_x: 2 layout_y: 2 row_skips: [[], []] Lattice_caBGA-381_17.0x17.0mm_Layout20x20_P0.8mm_Ball0.4mm_Pad0.4mm: description: "Lattice caBGA-381, ECP5 FPGAs" size_source: "http://www.latticesemi.com/view_document?document_id=213" body_size_x: 17.0 body_size_y: 17.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.075 layout_x: 20 layout_y: 20 row_skips: [[1, 20], [], [], [], [], [], [], [], [], [], [], [], [], [], [6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [], [], [], [], [1, 4, 9, 10, 13, 18, 20]] Lattice_caBGA-381_17.0x17.0mm_Layout20x20_P0.8mm_Ball0.4mm_Pad0.6mm_SMD: description: "Lattice caBGA-381, ECP5 FPGAs" size_source: "http://www.latticesemi.com/view_document?document_id=213" body_size_x: 17.0 body_size_y: 17.0 pitch: 0.8 pad_diameter: 0.6 mask_margin: -0.05 layout_x: 20 layout_y: 20 row_skips: [[1, 20], [], [], [], [], [], [], [], [], [], [], [], [], [], [6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [], [], [], [], [1, 4, 9, 10, 13, 18, 20]] Lattice_caBGA-756_27.0x27.0mm_Layout32x32_P0.8mm: description: "Lattice caBGA-756, ECP5 FPGAs" size_source: "http://www.latticesemi.com/view_document?document_id=213" body_size_x: 27.0 body_size_y: 27.0 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.075 layout_x: 32 layout_y: 32 row_skips: [[1, 6, 12, 21, 27, 32], [6, 12, 21, 27], [6, 12, 21, 27], [6, 12, 21, 27], [6, 12, 21, 27], [6, 7, 12, 21, 26, 27], [1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 20, 21, 25, 26, 27, 28, 29, 30, 31, 32], [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26], [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], [8, 9, 24, 25], [8, 9, 24, 25], [1, 2, 3, 4, 5, 6, 7, 8, 9, 24, 25, 26, 27, 28, 29, 30, 31, 32], [8, 9, 24, 25], [8, 9, 24, 25], [8, 9, 24, 25], [8, 9, 24, 25], [8, 9, 24, 25], [8, 9, 24, 25], [7, 8, 9, 24, 25, 26], [8, 9, 24, 25], [1, 2, 3, 4, 5, 6, 7, 8, 9, 24, 25, 26, 27, 28, 29, 30, 31, 32], [8, 9, 24, 25], [8, 9, 24, 25], [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13, 18, 21, 24, 25, 26, 27, 28, 29, 30, 31, 32], [6, 7, 8, 10, 13, 18, 21, 25, 26, 27], [6, 10, 13, 18, 21, 27], [6, 27], [6, 27], [6, 10, 13, 16, 19, 22, 25, 27], [1, 6, 10, 13, 16, 19, 22, 25, 27, 32]] Analog_BGA-28_4.0x6.25mm_Layout4x7_P0.8mm_Ball0.45mm_Pad0.4: description: "Analog BGA-28, 0.4mm pad" size_source: "https://www.analog.com/media/en/technical-documentation/data-sheets/8063fa.pdf" body_size_x: 4.0 body_size_y: 6.25 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 4 layout_y: 7 ST_uTFBGA-36_3.6x3.6mm_Layout6x6_P0.5mm: description: "ST uTFBGA-36, 0.25mm pad" size_source: "https://www.st.com/resource/en/datasheet/stulpi01a.pdf" body_size_x: 3.6 body_size_y: 3.6 pitch: 0.5 pad_diameter: 0.25 mask_margin: 0.05 layout_x: 6 layout_y: 6 WLP-9_1.448x1.468mm_Layout3x3_P0.4mm_Ball0.27mm_Pad0.25mm: description: "WLP-9" size_source: "https://pdfserv.maximintegrated.com/package_dwgs/21-100168.PDF" body_size_x: 1.468 body_size_y: 1.448 pitch: 0.4 pad_diameter: 0.27 mask_margin: 0.02 paste_margin: 0.000001 layout_x: 3 layout_y: 3 VFBGA-86_6x6mm_Layout10x10_P0.55mm_Ball0.25mm_Pad0.2mm: description: "VFBGA-86" size_source: "https://www.dialog-semiconductor.com/sites/default/files/da1469x_datasheet_3v1.pdf#page=740" body_size_x: 6.0 body_size_y: 6.0 pitch: 0.55 pad_diameter: 0.2 layout_x: 10 layout_y: 10 row_skips: [[], [6], [5, 7], [4, 7, 8], [3, 5, 7], [6, 8], [7], [4, 6], [], []] BGA-200_10.0x14.5mm_Layout12x22_P0.80x0.65mm: description: "BGA-200" size_source: "http://www.issi.com/WW/pdf/43-46LQ32256A-AL.pdf" body_size_x: 10.0 body_size_y: 14.5 pitch_x: 0.80 pitch_y: 0.65 pad_diameter: 0.27 layout_x: 12 layout_y: 22 row_skips: [[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[[1,13]],[[1,13]],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7],[6,7]] Infineon_LFBGA-292_17x17mm_Layout20x20_P0.8mm_Ball0.5mm_Pad0.35: description: "Infineon LFBGA-292, 0.35mm pad" size_source: "https://www.infineon.com/cms/en/product/packages/PG-LFBGA/PG-LFBGA-292-11/" body_size_x: 17.0 body_size_y: 17.0 pitch: 0.8 pad_diameter: 0.35 layout_x: 20 layout_y: 20 row_skips: [ [], [], [3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18], [3,18], [3,18], [3,6,7,8,9,10,11,12,13,14,15,18], [3,6,7,14,15,18], [3,6,8,13,15,18], [3,6,9,12,15,18], [3,6,15,18], [3,6,15,18], [3,6,9,12,15,18], [3,6,8,13,15,18], [3,6,7,14,15,18], [3,6,7,8,9,10,11,12,13,14,15,18], [3,18], [3,18], [3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18], [], [] ] ================================================ FILE: scripts/Packages/Package_BGA/bga_xilinx.yaml ================================================ # Artix-7 FPGA Packages # Notes: # - Often names are similiar, e.g. FB, FBG and FBV. I choose FBG as it is the common one. # The addition stems from different solder types for the BGA balls # - Xilinx_CPG236 and Xilinx_CPG238 are the same, different name comes from bank differences # - Xilinx_CSG324 and Xilinx_CSG325 are the same, different name comes from bank differences # - Xilinx_RS484 and Xilinx_SBG484 have same landing pattern but different heights/3D packages # - Xilinx_RB484, Xilinx_FBG484 and Xilinx_FGG484 have same landing pattern but different heights/3D packages # - Xilinx_RB676, Xilinx_FBG676 and Xilinx_FGG676 have same landing pattern but different heights/3D packages Xilinx_CPG236: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=266" additional_tags: "CP236 CPG236" body_size_x: 10 body_size_y: 10 pitch: 0.5 pad_diameter: 0.275 mask_margin: 0.05 layout_x: 19 layout_y: 19 row_skips: [[], [], [], [[4,17]], [[4,17]], [[4,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,7],[9,12],[14,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,17]], [[4,17]], [[4,17]], [], [], []] Xilinx_CPG238: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=267" additional_tags: "CPG238" body_size_x: 10 body_size_y: 10 pitch: 0.5 pad_diameter: 0.275 mask_margin: 0.05 layout_x: 19 layout_y: 19 row_skips: [[], [], [], [[4,17]], [[4,17]], [[4,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,7],[9,12],[14,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,7],[14,17]], [[4,17]], [[4,17]], [[4,17]], [], [], []] Xilinx_CSG324: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=268" additional_tags: "CS324 CSG324" body_size_x: 15 body_size_y: 15 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 18 layout_y: 18 Xilinx_CSG325: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=268" additional_tags: "CS325 CSG235" body_size_x: 15 body_size_y: 15 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 18 layout_y: 18 Xilinx_SBG484: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=270" additional_tags: "SB484 SBG484 SBV484" body_size_x: 19 body_size_y: 19 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 22 layout_y: 22 Xilinx_RS484: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=279" additional_tags: "RS484" body_size_x: 19 body_size_y: 19 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 22 layout_y: 22 Xilinx_FTG256: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=269" additional_tags: "FT256 FTG256" body_size_x: 17 body_size_y: 17 pitch: 1 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 16 layout_y: 16 Xilinx_FBG484: description: "Artix-7, Kintex-7 and Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=271, ttps://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=281, https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=82" additional_tags: "FB484 FBG484 FBV484" body_size_x: 23 body_size_y: 23 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 22 layout_y: 22 Xilinx_FGG484: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=275" additional_tags: "FG484 FGG484" body_size_x: 23 body_size_y: 23 pitch: 1 pad_diameter: 0.5 mask_margin: 0.05 layout_x: 22 layout_y: 22 Xilinx_RB484: description: "Artix-7 and Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=278, https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=92" additional_tags: "RB484" body_size_x: 23 body_size_y: 23 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 22 layout_y: 22 Xilinx_FBG676: description: "Artix-7, Kintex-7 and Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=273, https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=284, https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=84" additional_tags: "FB676 FBG676 FBV676" body_size_x: 27 body_size_y: 27 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 26 layout_y: 26 Xilinx_FGG676: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=276" additional_tags: "FG676 FGG676" body_size_x: 27 body_size_y: 27 pitch: 1 pad_diameter: 0.5 mask_margin: 0.05 layout_x: 26 layout_y: 26 Xilinx_RB676: description: "Artix-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=280" additional_tags: "RB676" body_size_x: 27 body_size_y: 27 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 26 layout_y: 26 Xilinx_FFG1156: description: "Artix-7, Kintex-7 and Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=277, https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=296, https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=91" additional_tags: "FF1156 FFG1156 FFV1156" body_size_x: 35 body_size_y: 35 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 34 layout_y: 34 # Spartan-7 FPGA Packages # Notes: Xilinx_CPGA196: description: "Spartan-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=260" additional_tags: "CPGA196" body_size_x: 8 body_size_y: 8 pitch: 0.5 pad_diameter: 0.275 mask_margin: 0.05 layout_x: 14 layout_y: 14 Xilinx_FTGB196: description: "Spartan-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=261" additional_tags: "FTGB196" body_size_x: 15 body_size_y: 15 pitch: 1 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 14 layout_y: 14 Xilinx_CSGA225: description: "Spartan-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=262" additional_tags: "CSGA225" body_size_x: 13 body_size_y: 13 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 15 layout_y: 15 Xilinx_CSGA324: description: "Spartan-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=263" additional_tags: "CSGA324" body_size_x: 15 body_size_y: 15 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 18 layout_y: 18 Xilinx_FGGA484: description: "Spartan-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=264" additional_tags: "FGGA484" body_size_x: 23 body_size_y: 23 pitch: 1 pad_diameter: 0.5 mask_margin: 0.05 layout_x: 22 layout_y: 22 Xilinx_FGGA676: description: "Spartan-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=265" additional_tags: "FGGA676" body_size_x: 27 body_size_y: 27 pitch: 1 pad_diameter: 0.5 mask_margin: 0.05 layout_x: 26 layout_y: 26 # Virtex-7 FPGA Packages # Notes: # - FFG1157 and FFG1158 have same footprint and same 3D package and are therefore in one footprint # - FFG1926, FFG1927, FFG1928 and FFG1930 have same footprint and same 3D package and are therefore in one footprint # - FLG1925, FLG1926, FLG1928 and FLG1930 have same footprint and same 3D package and are therefore in one footprint # - RF1157 and RF1158 have same footprint and same 3D package and are therefore in one footprint Xilinx_FFG1157_FFG1158: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=299" additional_tags: "FF1157 FFG1157 FFV1157 FF1158 FFG1158 FFV1158" body_size_x: 35 body_size_y: 35 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 34 layout_y: 34 Xilinx_FFG1761: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=300" additional_tags: "FF1761 FFG1761" body_size_x: 42.5 body_size_y: 42.5 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 42 layout_y: 42 row_skips: [[1,42], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [1,42]] Xilinx_FFV1761: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=301" additional_tags: "FFV1761" body_size_x: 42.5 body_size_y: 42.5 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 42 layout_y: 42 row_skips: [[1,42], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [1,42]] Xilinx_FHG1761: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=302" additional_tags: "FH1761 FHG1761" body_size_x: 45 body_size_y: 45 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 42 layout_y: 42 row_skips: [[1,42], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [1,42]] Xilinx_FFG1926_FFG1927_FFG1928_FFG1930: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=303" additional_tags: "FF1926 FFG1926 FF1927 FFG1927 FFV1927 FF1928 FFG1928 FF1930 FFG1930" body_size_x: 45 body_size_y: 45 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 44 layout_y: 44 row_skips: [[1,2,43,44], [1,44], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [1,44], [1,2,43,44]] Xilinx_FLG1925_FLG1926_FLG1928_FLG1930: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=304" additional_tags: "FL1925 FLG1925 FL1926 FLG1926 FL1928 FLG1928 FL1930 FLG1930" body_size_x: 45 body_size_y: 45 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 44 layout_y: 44 row_skips: [[1,2,43,44], [1,44], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [1,44], [1,2,43,44]] Xilinx_RF1157_RF1158: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=305" additional_tags: "RF1157 RF1158" body_size_x: 35 body_size_y: 35 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 34 layout_y: 34 Xilinx_RF1761: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=306" additional_tags: "RF1761" body_size_x: 42.5 body_size_y: 42.5 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 42 layout_y: 42 row_skips: [[1,42], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [1,42]] Xilinx_RF1930: description: "Virtex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=307" additional_tags: "RF1930" body_size_x: 45 body_size_y: 45 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 44 layout_y: 44 row_skips: [[1,2,43,44], [1,44], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [1,44], [1,2,43,44]] # Kintex-7 FPGA Packages # Notes: # - FBG484 has the same name for Artix and Kintex devices, although the 3d model is slightly different # - FBG676 has the same name for Artix and Kintex devices, although the 3d model is slightly different # - FF900, FFG900, FFV900, FF901, FFG901 and FFV901 have same footprint and same 3D package and are therefore in one footprint # - FFG1156 has the same name for Artix and Kintex devices # For Xilinx_FBG484 refer to Artix-7 models # For Xilinx_FBG676 refer to Artix-7 models Xilinx_FBG900: description: "Kintex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=289" additional_tags: "FB900 FBG900 FBV900" body_size_x: 31 body_size_y: 31 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 30 layout_y: 30 Xilinx_FFG676: description: "Kintex-7 and Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=292, https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=88" additional_tags: "FF676 FFG676 FFV676" body_size_x: 27 body_size_y: 27 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 26 layout_y: 26 Xilinx_FFG900_FFG901: description: "Kintex-7 and Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=294, https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=90" additional_tags: "FF900 FFG900 FFV900 FF901 FFG901 FFV901" body_size_x: 31 body_size_y: 31 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 30 layout_y: 30 # For Xilinx_FFG1156 refer to Artix-7 Xilinx_RF676: description: "Kintex-7 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=297" additional_tags: "RF676" body_size_x: 27 body_size_y: 27 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 26 layout_y: 26 Xilinx_RF900: description: "Kintex-7 and Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug475_7Series_Pkg_Pinout.pdf#page=298, https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=94" additional_tags: "RF900" body_size_x: 31 body_size_y: 31 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 30 layout_y: 30 # Zynq-7000 FPGA Packages # Notes: # - Xilinx_FBG484 has the same name for Artix and Zynq devices # - Xilinx_FBG676 has the same name for Artix and Zynq devices # - Xilinx_FFG676 has the same name for Kintex and Zynq devices # - Xilinx_FFG900_FFG901 has the same name for Kintex and Zynq devices # - Xilinx_FFG1156 has the same name for Artix and Zynq devices # - Xilinx_RB484 has the same name for Artix and Zynq devices # - Xilinx_RF900 has the same name for Kintex and Zynq devices Xilinx_CLG225: description: "Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=77" additional_tags: "CLG225" body_size_x: 13 body_size_y: 13 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 15 layout_y: 15 Xilinx_CLG400: description: "Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=78" additional_tags: "CLG400 CL400" body_size_x: 17 body_size_y: 17 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 20 layout_y: 20 Xilinx_CLG484_CLG485: description: "Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=79" additional_tags: "CLG484 CL484 CLG485 CL485" body_size_x: 19 body_size_y: 19 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 22 layout_y: 22 Xilinx_SBG485: description: "Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=80" additional_tags: "SBG485 SBV485" body_size_x: 19 body_size_y: 19 pitch: 0.8 pad_diameter: 0.4 mask_margin: 0.05 layout_x: 22 layout_y: 22 # For Xilinx_FBG484 refer to Artix-7 # For Xilinx_FBG676 refer to Artix-7 # For Xilinx_FFG676 refer to Kintex-7 # For Xilinx_FFG900_FFG901 refer to Kintex-7 # For Xilinx_FFG1156 refer to Artix-7 # For Xilinx_RB484 refer to Artix-7 Xilinx_RFG676: description: "Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=93" additional_tags: "RF676 RFG676" body_size_x: 27 body_size_y: 27 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 26 layout_y: 26 # For Xilinx_RF900 refer to Kintex-7 Xilinx_RF1156: description: "Zynq-7000 BGA, NSMD pad definition Appendix A" size_source: "https://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf#page=95" additional_tags: "RF1156" body_size_x: 35 body_size_y: 35 pitch: 1 pad_diameter: 0.53 mask_margin: 0.05 layout_x: 34 layout_y: 34 ================================================ FILE: scripts/Packages/Package_BGA/csp.yaml ================================================ WLCSP-12_1.403x1.555mm_P0.4mm_Stagger: description: "WLCSP-12, staggered array" size_source: "http://ww1.microchip.com/downloads/en/devicedoc/atmel-8235-8-bit-avr-microcontroller-attiny20_datasheet.pdf#page=208" body_size_x: 1.403 body_size_y: 1.555 pitch_x: 0.2 pitch_y: 0.346333 pad_diameter: 0.215 mask_margin: 0.0325 paste_margin: 0.000001 layout_x: 6 layout_y: 4 row_skips: [[2, 4, 6], [1, 3, 5], [2, 4, 6], [1, 3, 5]] ST_WLCSP-25_Die425: description: "WLCSP-25" size_source: "http://www.st.com/resource/en/datasheet/stm32l031f6.pdf#page=112" body_size_x: 2.097 body_size_y: 2.493 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 5 layout_y: 5 ST_WLCSP-25_Die444: description: "WLCSP-25" size_source: "http://www.st.com/resource/en/datasheet/stm32f031k6.pdf#page=93" body_size_x: 2.423 body_size_y: 2.325 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 5 layout_y: 5 ST_WLCSP-25_Die457: description: "WLCSP-25" size_source: "http://www.st.com/resource/en/datasheet/stm32l011k3.pdf#page=100" body_size_x: 2.133 body_size_y: 2.070 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 5 layout_y: 5 ST_WLCSP-36_Die417: description: "WLCSP-36" size_source: "http://www.st.com/resource/en/datasheet/stm32l052t8.pdf#page=123" body_size_x: 2.61 body_size_y: 2.88 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 6 layout_y: 6 ST_WLCSP-36_Die440: description: "WLCSP-36" size_source: "http://www.st.com/resource/en/datasheet/stm32f051t8.pdf#page=103" body_size_x: 2.605 body_size_y: 2.703 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 6 layout_y: 6 ST_WLCSP-36_Die445: description: "WLCSP-36" size_source: "http://www.st.com/resource/en/datasheet/stm32f042k6.pdf#page=96" body_size_x: 2.605 body_size_y: 2.703 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 6 layout_y: 6 ST_WLCSP-36_Die458: description: "WLCSP-36" size_source: "http://www.st.com/resource/en/datasheet/stm32f410t8.pdf#page=119" body_size_x: 2.553 body_size_y: 2.579 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 6 layout_y: 6 ST_WLCSP-49_Die423: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/stm32f401vc.pdf#page=115" body_size_x: 2.965 body_size_y: 2.965 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 7 layout_y: 7 ST_WLCSP-49_Die431: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/stm32f411vc.pdf#page=124" body_size_x: 2.999 body_size_y: 3.185 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 7 layout_y: 7 ST_WLCSP-49_Die433: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/stm32f401ce.pdf#page=116" body_size_x: 3.029 body_size_y: 3.029 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 7 layout_y: 7 ST_WLCSP-49_Die435: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/DM00257211.pdf#page=191" body_size_x: 3.141 body_size_y: 3.127 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 7 layout_y: 7 ST_WLCSP-49_Die438: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/stm32f303r8.pdf#page=112" body_size_x: 3.89 body_size_y: 3.74 pitch: 0.5 pad_diameter: 0.29 mask_margin: 0.03 paste_margin: 0.01 layout_x: 7 layout_y: 7 ST_WLCSP-49_Die439: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/stm32f301r8.pdf#page=117" body_size_x: 3.417 body_size_y: 3.151 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 7 layout_y: 7 ST_WLCSP-49_Die447: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/stm32l072kz.pdf#page=134" body_size_x: 3.294 body_size_y: 3.258 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 7 layout_y: 7 ST_WLCSP-49_Die448: description: "WLCSP-49" size_source: "http://www.st.com/resource/en/datasheet/stm32f071v8.pdf#page=106" body_size_x: 3.277 body_size_y: 3.109 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 7 layout_y: 7 ST_WLCSP-63_Die427: description: "WLCSP-63" size_source: "http://www.st.com/resource/en/datasheet/stm32l151cc.pdf#page=125" body_size_x: 3.228 body_size_y: 4.164 pitch: 0.4 pad_diameter: 0.24 mask_margin: 0.0325 paste_margin: 0.000001 layout_x: 7 layout_y: 9 ST_WLCSP-64_Die414: description: "WLCSP-64" size_source: "http://www.st.com/resource/en/datasheet/stm32f103ze.pdf#page=120" body_size_x: 4.466 body_size_y: 4.395 pitch: 0.5 pad_diameter: 0.25 mask_margin: 0.025 paste_margin: 0.035 layout_x: 8 layout_y: 8 ST_WLCSP-64_Die427: description: "WLCSP-64" size_source: "http://www.st.com/resource/en/datasheet/stm32l152zc.pdf#page=126" body_size_x: 4.539 body_size_y: 4.911 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 8 layout_y: 8 ST_WLCSP-64_Die435: description: "WLCSP-64" size_source: "http://www.st.com/resource/en/datasheet/DM00257211.pdf#page=188" body_size_x: 3.141 body_size_y: 3.127 pitch: 0.35 pad_diameter: 0.21 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 8 layout_y: 8 ST_WLCSP-64_Die436: description: "WLCSP-64" size_source: "http://www.st.com/resource/en/datasheet/stm32l152zd.pdf#page=143" body_size_x: 4.539 body_size_y: 4.911 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 8 layout_y: 8 ST_WLCSP-64_Die441: description: "WLCSP-64" size_source: "http://www.st.com/resource/en/datasheet/DM00213872.pdf#page=167" body_size_x: 3.623 body_size_y: 3.651 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 8 layout_y: 8 ST_WLCSP-64_Die442: description: "WLCSP-64" size_source: "http://www.st.com/resource/en/datasheet/stm32f091vb.pdf#page=109" body_size_x: 3.347 body_size_y: 3.585 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 8 layout_y: 8 ST_WLCSP-64_Die462: description: "WLCSP-64" size_source: "http://www.st.com/resource/en/datasheet/DM00340475.pdf#page=189" body_size_x: 3.357 body_size_y: 3.657 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 8 layout_y: 8 ST_WLCSP-66_Die411: description: "WLCSP-66" size_source: "http://www.st.com/resource/en/datasheet/stm32f207vg.pdf#page=154" body_size_x: 3.639 body_size_y: 3.971 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 9 layout_y: 9 row_skips: [[], [], [[4, 7]], [[4, 7]], [[4, 7]], [[4, 7]], [[4, 7]], [], []] ST_WLCSP-66_Die432: description: "WLCSP-66" size_source: "http://www.st.com/resource/en/datasheet/stm32f378vc.pdf#page=114" body_size_x: 3.767 body_size_y: 4.229 pitch: 0.4 pad_diameter: 0.24 mask_margin: 0.0325 paste_margin: 0.000001 layout_x: 8 layout_y: 9 row_skips: [[], [], [], [4, 5], [4, 5], [4, 5], [], [], []] ST_WLCSP-72_Die415: description: "WLCSP-72" size_source: "http://www.st.com/resource/en/datasheet/stm32l476me.pdf#page=255" body_size_x: 4.4084 body_size_y: 3.7594 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 9 layout_y: 9 row_skips: [[], [], [], [[4, 7]], [[4, 7]], [[4, 7]], [], [], []] ST_WLCSP-81_Die415: description: "WLCSP-81" size_source: "http://www.st.com/resource/en/datasheet/stm32l476me.pdf#page=252" body_size_x: 4.4084 body_size_y: 3.7594 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 9 layout_y: 9 ST_WLCSP-81_Die421: description: "WLCSP-81" size_source: "http://www.st.com/resource/en/datasheet/stm32f446ze.pdf#page=192" body_size_x: 3.693 body_size_y: 3.815 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 9 layout_y: 9 ST_WLCSP-81_Die463: description: "WLCSP-81" size_source: "http://www.st.com/resource/en/datasheet/DM00282249.pdf#page=175" body_size_x: 4.039 body_size_y: 3.951 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 9 layout_y: 9 ST_WLCSP-90_Die413: description: "WLCSP-90" size_source: "http://www.st.com/resource/en/datasheet/stm32f405og.pdf#page=164" body_size_x: 4.223 body_size_y: 3.969 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 10 layout_y: 9 ST_WLCSP-100_Die422: description: "WLCSP-100" size_source: "http://www.st.com/resource/en/datasheet/stm32f302vc.pdf#page=133" body_size_x: 4.201 body_size_y: 4.663 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.000001 layout_x: 10 layout_y: 10 ST_WLCSP-100_Die446: description: "WLCSP-100" size_source: "http://www.st.com/resource/en/datasheet/stm32f303zd.pdf#page=162" body_size_x: 4.775 body_size_y: 5.041 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.000001 layout_x: 10 layout_y: 10 ST_WLCSP-100_Die452: description: "WLCSP-100" size_source: "http://www.st.com/resource/en/datasheet/DM00330506.pdf#page=218" body_size_x: 4.201 body_size_y: 4.663 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.000001 layout_x: 10 layout_y: 10 ST_WLCSP-100_Die461: description: "WLCSP-100" size_source: "http://www.st.com/resource/en/datasheet/DM00284211.pdf#page=259" body_size_x: 4.618 body_size_y: 4.142 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.000001 layout_x: 10 layout_y: 10 ST_WLCSP-104_Die437: description: "WLCSP-104" size_source: "http://www.st.com/resource/en/datasheet/stm32l152ze.pdf#page=127" body_size_x: 4.095 body_size_y: 5.094 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 9 layout_y: 12 row_skips: [[], [], [], [], [5], [5], [5], [5], [], [], [], []] ST_WLCSP-143_Die419: description: "WLCSP-143" size_source: "http://www.st.com/resource/en/datasheet/stm32f429ng.pdf#page=203" body_size_x: 4.521 body_size_y: 5.547 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 11 layout_y: 13 ST_WLCSP-143_Die449: description: "WLCSP-143" size_source: "http://www.st.com/resource/en/datasheet/stm32f746zg.pdf#page=202" body_size_x: 4.539 body_size_y: 5.849 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 11 layout_y: 13 ST_WLCSP-144_Die470: description: "WLCSP-144" size_source: "http://www.st.com/resource/en/datasheet/DM00366448.pdf#page=295" body_size_x: 5.24 body_size_y: 5.24 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 12 layout_y: 12 ST_WLCSP-168_Die434: description: "WLCSP-168" size_source: "http://www.st.com/resource/en/datasheet/stm32f469ni.pdf#page=198" body_size_x: 4.891 body_size_y: 5.692 pitch: 0.4 pad_diameter: 0.22 mask_margin: 0.04 paste_margin: 0.000001 layout_x: 12 layout_y: 14 ST_WLCSP-180_Die451: description: "WLCSP-180" size_source: "http://www.st.com/resource/en/datasheet/DM00273119.pdf#page=240" body_size_x: 5.537 body_size_y: 6.095 pitch: 0.4 pad_diameter: 0.225 mask_margin: 0.0325 paste_margin: 0.0125 layout_x: 13 layout_y: 14 row_skips: [[], [], [], [], [], [], [7], [7], [], [], [], [], [], []] WLCSP-16_1.409x1.409mm_P0.35mm: description: "WLCSP-16" size_source: 'http://www.latticesemi.com/view_document?document_id=213' body_size_x: 1.409 body_size_y: 1.409 pitch: 0.35 pad_diameter: 0.2 layout_x: 4 layout_y: 4 WLCSP-8_1.551x2.284mm_P0.5mm: description: "WLCSP-8" size_source: "https://www.adestotech.com/wp-content/uploads/AT25SL321_112.pdf#page=75" body_size_x: 1.551 body_size_y: 2.284 pitch: 0.5 pad_diameter: 0.2 layout_x: 2 layout_y: 4 WLCSP-4-X1-WLB0909-4_0.89x0.89mm_P0.5mm: description: "X1-WLB0909" size_source: 'https://www.diodes.com/assets/Datasheets/AP22913.pdf' body_size_x: 0.89 body_size_y: 0.89 pitch: 0.5 pad_diameter: 0.235 # even though ball_diameter is 0.235 analog recommends a landing pad of 0.235 layout_x: 2 layout_y: 2 ================================================ FILE: scripts/Packages/Package_BGA/ipc_7351b_bga_land_patterns.yaml ================================================ # IPC IPC-7351B (sadly no openly accessible document available) # Page 89, Table 14-5 and 14-6 # First level: ball type (collapsible is most common so use if unknown) # Second level: nominal ball diameter # Third level: land pattern diameter in nominal and min/max variation # IPC-7351B section 14.4.2 requires the use of the max land size # Furthermore, that section also suggests NSMD lands are preferred 'collapsible': 0.75: nominal: 0.55 max: 0.6 min: 0.5 0.65: nominal: 0.5 max: 0.55 min: 0.45 0.6: nominal: 0.45 max: 0.5 min: 0.4 0.55: nominal: 0.4 max: 0.5 min: 0.4 0.5: nominal: 0.4 max: 0.45 min: 0.35 0.45: nominal: 0.35 max: 0.4 min: 0.3 0.4: nominal: 0.3 max: 0.35 min: 0.25 0.35: nominal: 0.28 max: 0.33 min: 0.23 0.3: nominal: 0.25 max: 0.25 min: 0.2 0.25: nominal: 0.2 max: 0.2 min: 0.17 0.2: nominal: 0.17 max: 0.2 min: 0.14 0.17: nominal: 0.15 max: 0.18 min: 0.12 0.15: nominal: 0.13 max: 0.15 min: 0.1 'non-collapsible': 0.75: nominal: 0.85 max: 0.9 min: 0.8 0.6: nominal: 0.7 max: 0.75 min: 0.65 0.55: nominal: 0.65 max: 0.7 min: 0.6 0.5: nominal: 0.55 max: 0.6 min: 0.5 0.45: nominal: 0.5 max: 0.55 min: 0.45 0.4: nominal: 0.45 max: 0.5 min: 0.4 0.3: nominal: 0.33 max: 0.38 min: 0.28 0.25: nominal: 0.28 max: 0.33 min: 0.23 0.2: nominal: 0.21 max: 0.24 min: 0.18 0.17: nominal: 0.18 max: 0.21 min: 0.15 0.15: nominal: 0.16 max: 0.19 min: 0.13 ================================================ FILE: scripts/Packages/Package_BGA/ipc_bga_generator.py ================================================ #!/usr/bin/env python3 import math import os import sys import argparse import yaml # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from KicadModTree import * import itertools from string import ascii_uppercase def generateFootprint(config, fpParams, fpId): createFp = False # use IPC-derived pad size if possible, then fall back to user-defined pads if "ball_type" in fpParams and "ball_diameter" in fpParams: try: padSize = configuration[fpParams["ball_type"]] try: padSize = configuration[fpParams["ball_type"]][fpParams["ball_diameter"]]["max"] fpParams["pad_size"] = [padSize, padSize] createFp = True except KeyError as e: print("{}mm is an invalid ball diameter. See ipc_7351b_bga_land_patterns.yaml for valid values. No footprint generated.".format(e)) except KeyError: print("{} is an invalid ball type. See ipc_7351b_bga_land_patterns.yaml for valid values. No footprint generated.".format(e)) if "pad_diameter" in fpParams: print("Pad size is being derived using IPC rules even though pad diameter is defined.") elif "ball_type" in fpParams and not "ball_diameter" in fpParams: raise KeyError("Ball diameter is missing. No footprint generated.") elif "ball_diameter" in fpParams and not "ball_type" in fpParams: raise KeyError("Ball type is missing. No footprint generated.") elif "pad_diameter" in fpParams: fpParams["pad_size"] = [fpParams["pad_diameter"], fpParams["pad_diameter"]] print("Pads size is set by the footprint definition. This should only be done for manufacturer-specific footprints.") createFp = True else: print("The config file must include 'ball_type' and 'ball_diameter' or 'pad_diameter'. No footprint generated.") if createFp: __createFootprintVariant(config, fpParams, fpId) def __createFootprintVariant(config, fpParams, fpId): pkgX = fpParams["body_size_x"] pkgY = fpParams["body_size_y"] layoutX = fpParams["layout_x"] layoutY = fpParams["layout_y"] if "additional_tags" in fpParams: additionalTag = " " + fpParams["additional_tags"] else: additionalTag = "" if "row_names" in fpParams: rowNames = fpParams["row_names"] else: rowNames = config['row_names'] if "row_skips" in fpParams: rowSkips = fpParams["row_skips"] else: rowSkips = [] # must be given pitch (equal in X and Y) or a unique pitch in both X and Y if "pitch" in fpParams: if "pitch_x" and "pitch_y" in fpParams: raise KeyError('{}: Either pitch or both pitch_x and pitch_y must be given.'.format(fpId)) else: pitchString = str(fpParams["pitch"]) pitchX = fpParams["pitch"] pitchY = fpParams["pitch"] else: if "pitch_x" and "pitch_y" in fpParams: pitchString = str(fpParams["pitch_x"]) + "x" + str(fpParams["pitch_y"]) pitchX = fpParams["pitch_x"] pitchY = fpParams["pitch_y"] else: raise KeyError('{}: Either pitch or both pitch_x and pitch_y must be given.'.format(fpId)) f = Footprint(fpId) f.setAttribute("smd") if "mask_margin" in fpParams: f.setMaskMargin(fpParams["mask_margin"]) if "paste_margin" in fpParams: f.setPasteMargin(fpParams["paste_margin"]) if "paste_ratio" in fpParams: f.setPasteMarginRatio(fpParams["paste_ratio"]) s1 = [1.0, 1.0] s2 = [min(1.0, round(pkgX / 4.3, 2))] * 2 t1 = 0.15 * s1[0] t2 = 0.15 * s2[0] padShape = Pad.SHAPE_CIRCLE if "pad_shape" in fpParams: if fpParams["pad_shape"] == "rect": padShape = Pad.SHAPE_RECT if fpParams["pad_shape"] == "roundrect": padShape = Pad.SHAPE_ROUNDRECT chamfer = min(config['fab_bevel_size_absolute'], min(pkgX, pkgY) * config['fab_bevel_size_relative']) silkOffset = config['silk_fab_offset'] crtYdOffset = config['courtyard_offset']['bga'] def crtYdRound(x): # Round away from zero for proper courtyard calculation neg = x < 0 if neg: x = -x x = math.ceil(x * 100) / 100.0 if neg: x = -x return x xCenter = 0.0 xLeftFab = xCenter - pkgX / 2.0 xRightFab = xCenter + pkgX / 2.0 xChamferFab = xLeftFab + chamfer xPadLeft = xCenter - pitchX * ((layoutX - 1) / 2.0) xPadRight = xCenter + pitchX * ((layoutX - 1) / 2.0) xLeftCrtYd = crtYdRound(xCenter - (pkgX / 2.0 + crtYdOffset)) xRightCrtYd = crtYdRound(xCenter + (pkgX / 2.0 + crtYdOffset)) yCenter = 0.0 yTopFab = yCenter - pkgY / 2.0 yBottomFab = yCenter + pkgY / 2.0 yChamferFab = yTopFab + chamfer yPadTop = yCenter - pitchY * ((layoutY - 1) / 2.0) yPadBottom = yCenter + pitchY * ((layoutY - 1) / 2.0) yTopCrtYd = crtYdRound(yCenter - (pkgY / 2.0 + crtYdOffset)) yBottomCrtYd = crtYdRound(yCenter + (pkgY / 2.0 + crtYdOffset)) yRef = yTopFab - 1.0 yValue = yBottomFab + 1.0 xLeftSilk = xLeftFab - silkOffset xRightSilk = xRightFab + silkOffset xChamferSilk = xLeftSilk + chamfer yTopSilk = yTopFab - silkOffset yBottomSilk = yBottomFab + silkOffset yChamferSilk = yTopSilk + chamfer wFab = configuration['fab_line_width'] wCrtYd = configuration['courtyard_line_width'] wSilkS = configuration['silk_line_width'] # Text f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s1, thickness=t1)) f.append(Text(type="value", text=fpId, at=[xCenter, yValue], layer="F.Fab", size=s1, thickness=t1)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=s2, thickness=t2)) # Fab f.append(PolygoneLine(polygone=[[xRightFab, yBottomFab], [xLeftFab, yBottomFab], [xLeftFab, yChamferFab], [xChamferFab, yTopFab], [xRightFab, yTopFab], [xRightFab, yBottomFab]], layer="F.Fab", width=wFab)) # Courtyard f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) # Silk f.append(PolygoneLine(polygone=[[xChamferSilk, yTopSilk], [xRightSilk, yTopSilk], [xRightSilk, yBottomSilk], [xLeftSilk, yBottomSilk], [xLeftSilk, yChamferSilk]], layer="F.SilkS", width=wSilkS)) # Pads balls = layoutX * layoutY if rowSkips == []: for _ in range(layoutY): rowSkips.append([]) for rowNum, row in zip(range(layoutY), rowNames): rowSet = set(range(1, layoutX + 1)) for item in rowSkips[rowNum]: try: # If item is a range, remove that range rowSet -= set(range(*item)) balls -= item[1] - item[0] except TypeError: # If item is an int, remove that int rowSet -= {item} balls -= 1 for col in rowSet: f.append(Pad(number="{}{}".format(row, col), type=Pad.TYPE_SMT, shape=padShape, at=[xPadLeft + (col-1) * pitchX, yPadTop + rowNum * pitchY], size=fpParams["pad_size"], layers=Pad.LAYERS_SMT, radius_ratio=config['round_rect_radius_ratio'])) # If this looks like a CSP footprint, use the CSP 3dshapes library packageType = 'CSP' if 'BGA' not in fpId and 'CSP' in fpId else 'BGA' f.append(Model(filename="{}Package_{}.3dshapes/{}.wrl".format( config['3d_model_prefix'], packageType, fpId))) f.setDescription("{0}, {1}x{2}mm, {3} Ball, {4}x{5} Layout, {6}mm Pitch, {7}".format(fpParams["description"], pkgY, pkgX, balls, layoutX, layoutY, pitchString, fpParams["size_source"])) f.setTags("{} {} {}{}".format(packageType, balls, pitchString, additionalTag)) outputDir = 'Package_{lib_name:s}.pretty/'.format(lib_name=packageType) if not os.path.isdir(outputDir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(outputDir) filename = '{outdir:s}{fpId:s}.kicad_mod'.format(outdir=outputDir, fpId=fpId) file_handler = KicadFileHandler(f) file_handler.writeFile(filename) def rowNameGenerator(seq): for n in itertools.count(1): for s in itertools.product(seq, repeat = n): yield ''.join(s) if __name__ == '__main__': parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('files', metavar='file', type=str, nargs='+', help='list of files holding information about what devices should be created.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') # parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../package_config_KLCv3.yaml') parser.add_argument('--ipc_doc', type=str, nargs='?', help='IPC definition document', default='ipc_7351b_bga_land_patterns.yaml') parser.add_argument('-v', '--verbose', action='count', help='set debug level') args = parser.parse_args() if args.verbose: DEBUG_LEVEL = args.verbose with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) # with open(args.series_config, 'r') as config_stream: # try: # configuration.update(yaml.safe_load(config_stream)) # except yaml.YAMLError as exc: # print(exc) with open(args.ipc_doc, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) # generate dict of A, B .. Y, Z, AA, AB .. CY less easily-confused letters rowNamesList = [x for x in ascii_uppercase if x not in ["I", "O", "Q", "S", "X", "Z"]] configuration.update({'row_names': list(itertools.islice(rowNameGenerator(rowNamesList), 80))}) for filepath in args.files: with open(filepath, 'r') as command_stream: try: cmd_file = yaml.safe_load(command_stream) except yaml.YAMLError as exc: print(exc) for pkg in cmd_file: print("generating part for parameter set {}".format(pkg)) generateFootprint(configuration, cmd_file[pkg], pkg) ================================================ FILE: scripts/Packages/Package_BGA/test_ipc.yaml ================================================ # these test the IPC pad size generator and error handling # uses IPC pads with collapsible balls Collapsible_balls: description: 'BGA-100' size_source: '' body_size_x: 6.0 body_size_y: 6.0 pitch: 0.55 ball_type: 'collapsible' ball_diameter: 0.25 layout_x: 10 layout_y: 10 Non-collapsible_balls: description: 'BGA-100' size_source: '' body_size_x: 6.0 body_size_y: 6.0 pitch: 0.55 ball_type: 'non-collapsible' ball_diameter: 0.25 layout_x: 10 layout_y: 10 Fixed_pad_size: description: 'BGA-100' size_source: '' body_size_x: 6.0 body_size_y: 6.0 pitch: 0.55 pad_diameter: 0.21 layout_x: 10 layout_y: 10 # warning as both fixed pad size and IPD ball info present Doubled_pad_size: description: 'BGA-100' size_source: '' body_size_x: 6.0 body_size_y: 6.0 pitch: 0.55 pad_diameter: 0.22 ball_type: 'collapsible' ball_diameter: 0.25 layout_x: 10 layout_y: 10 # failure as ball diameter is not in the IPC table # can also change ball type to an illegal value Invalid_ball_size: description: 'BGA-100' size_source: '' body_size_x: 6.0 body_size_y: 6.0 pitch: 0.55 ball_type: 'collapsible' # change this to an illegal value ball_diameter: 0.1234 # not an IPC ball diameter layout_x: 10 layout_y: 10 # failure as ball_diameter is given but not ball_type # can also test condition where ball type is given by not diameter Missing_ball_type: description: 'BGA-100' size_source: '' body_size_x: 6.0 body_size_y: 6.0 pitch: 0.55 ball_diameter: 0.25 layout_x: 10 layout_y: 10 ================================================ FILE: scripts/Packages/Package_DIP/make_DIP_footprints.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_DIP import * if __name__ == '__main__': # common settings overlen_top=1.27 overlen_bottom=1.27 rm=2.54 ddrill=0.8 pad=[1.6,1.6] pad_large=[2.4,1.6] pad_smdsocket=[3.1,1.6] pad_smdsocket_small=[1.6,1.6] # narrow 7.62 DIPs pins=[4,6,8,10,12,14,16,18,20,22,24,28] pinrow_distance=7.62 package_width=6.35 socket_width=pinrow_distance+2.54 for p in pins: makeDIP(p,rm,pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad,False,0,0,0) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, 0,0,0, ["LongPads"]) socket_height = (p / 2 - 1) * rm + 2.54 makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, False, socket_width,socket_height,0, ["Socket"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, socket_width,socket_height,0, ["Socket","LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket, True, socket_width,socket_height,1.27, ["SMDSocket","LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket_small, True,socket_width, socket_height, 0, ["SMDSocket", "SmallPads"]) # narrow 7.62 DIPs pins=[4,6,8,10,12,14,16,] pinrow_distance=10.16 package_width=6.35 socket_width=pinrow_distance+2.54 for p in pins: makeDIP(p,rm,pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad,False,0,0,0) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, 0,0,0, ["LongPads"]) # mid 10.16 DIPs pins=[22,24] pinrow_distance=10.16 package_width=9.14 socket_width=pinrow_distance+2.54 for p in pins: makeDIP(p,rm,pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad,False,0,0,0) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, 0,0,0, ["LongPads"]) socket_height = (p / 2 - 1) * rm + 2.54 makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, False, socket_width,socket_height,0, ["Socket"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, socket_width,socket_height,0, ["Socket","LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket, True, socket_width, socket_height, 1.27, ["SMDSocket", "LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket_small, True, socket_width, socket_height, 0, ["SMDSocket", "SmallPads"]) # mid 15.24 DIPs pins=[24,28,32,40,42,48,64] pinrow_distance=15.24 package_width=14.73 socket_width=pinrow_distance+2.54 for p in pins: makeDIP(p,rm,pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad,False,0,0,0) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, 0,0,0, ["LongPads"]) socket_height = (p / 2 - 1) * rm + 2.54 makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, False, socket_width,socket_height,0, ["Socket"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, socket_width,socket_height,0, ["Socket","LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket, True, socket_width, socket_height, 1.27, ["SMDSocket", "LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket_small, True, socket_width, socket_height, 0, ["SMDSocket", "SmallPads"]) # large 22.86 DIPs pins=[64] pinrow_distance=22.86 package_width=22.35 socket_width=pinrow_distance+2.54 for p in pins: makeDIP(p,rm,pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad,False,0,0,0) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, 0,0,0, ["LongPads"]) socket_height = (p / 2 - 1) * rm + 2.54 makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, False, socket_width,socket_height,0, ["Socket"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, socket_width,socket_height,0, ["Socket","LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket, True, socket_width, socket_height, 1.27, ["SMDSocket", "LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket_small, True, socket_width, socket_height, 0, ["SMDSocket", "SmallPads"]) # large 25.4 DIPs pins=[40,64] pinrow_distance=25.4 package_width=24.89 socket_width=pinrow_distance+2.54 for p in pins: makeDIP(p,rm,pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad,False,0,0,0) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, 0,0,0, ["LongPads"]) socket_height = (p / 2 - 1) * rm + 2.54 makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, False, socket_width,socket_height,0, ["Socket"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, socket_width,socket_height,0, ["Socket","LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket, True, socket_width, socket_height, 1.27, ["SMDSocket", "LongPads"]) makeDIP(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smdsocket_small, True, socket_width, socket_height, 0, ["SMDSocket", "SmallPads"]) # special SMD footprints smd_pins=[4,6,8,10,12,14,16,18,20,22,24,32] pad_smd = [2, 1.78] smd_pinrow_distances=[7.62, 9.53, 11.48] package_width=6.35 for p in smd_pins: for prd in smd_pinrow_distances: makeDIP(p, rm, prd, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, True, 0,0,0, [], "Housings_DIP", [0, 0, 0], [1, 1, 1], [0, 0, 0], 'SMDIP', 'surface-mounted (SMD) DIP', 'SMD DIP DIL PDIP SMDIP') smd_pins=[4,6,8,10,12,14,16,18,20,22] pad_smd = [1.5, 1.78] smd_pinrow_distances=[9.53] package_width=6.35 for p in smd_pins: for prd in smd_pinrow_distances: makeDIP(p, rm, prd, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, True, 0,0,0, ['Clearance8mm'], "Housings_DIP", [0, 0, 0], [1, 1, 1], [0, 0, 0], 'SMDIP', 'surface-mounted (SMD) DIP', 'SMD DIP DIL PDIP SMDIP') smd_pins=[24,28,32,40,42,48,64] pad_smd = [2, 1.78] smd_pinrow_distances=[15.24] package_width=14.73 for p in smd_pins: for prd in smd_pinrow_distances: makeDIP(p, rm, prd, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, True, 0,0,0, [], "Housings_DIP", [0, 0, 0], [1, 1, 1], [0, 0, 0], 'SMDIP', 'surface-mounted (SMD) DIP', 'SMD DIP DIL PDIP SMDIP') smd_pins=[40] pad_smd = [2, 1.78] smd_pinrow_distances=[25.24] package_width=24.89 for p in smd_pins: for prd in smd_pinrow_distances: makeDIP(p, rm, prd, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, True, 0,0,0, [], "Housings_DIP", [0, 0, 0], [1, 1, 1], [0, 0, 0], 'SMDIP', 'surface-mounted (SMD) DIP', 'SMD DIP DIL PDIP SMDIP') # DIP-switches: pins=[2,4,6,8,10,12,14,16,18,20,22,24] pinrow_distance = 7.62 package_width = 9.78 switch_width=4.06 switch_height=1.27 overlen_top = 2.36 overlen_bottom = 2.36 package_width_narrow = 6.68 switch_width_narrow = 3.62 switch_height_narrow = 1.27 overlen_top_narrow = 2.05 overlen_bottom_narrow = 2.05 pad_smd=[2.44,1.12] pinrow_distance_smd=8.61 switch_width_piano=1.8 switch_height_piano=1.5 package_width_piano=10.8 overlen_top_piano = 2.05 overlen_bottom_piano = 2.05 for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, switch_width, switch_height, 'Slide', False, []) makeDIPSwitch(p, rm, pinrow_distance, package_width_narrow, overlen_top_narrow, overlen_bottom_narrow, ddrill, pad, switch_width_narrow, switch_height_narrow, 'Slide', False, ["LowProfile"]) makeDIPSwitch(p, rm, pinrow_distance_smd, package_width_narrow, overlen_top_narrow, overlen_bottom_narrow, ddrill, pad_smd, switch_width_narrow, switch_height_narrow, 'Slide', True,["SMD","LowProfile"], 'Buttons_Switches_SMD') makeDIPSwitch(p, rm, pinrow_distance, package_width_piano, overlen_top_piano, overlen_bottom_piano, ddrill, pad, switch_width_piano, switch_height_piano, 'Piano', False, []) # Copal CVS DIP-switches (http://www.nidec-copal-electronics.com/e/catalog/switch/cvs.pdf): pins = [2, 4, 6, 8, 16] rm = 1 pinrow_distance = 5.9 package_width = 4.7 switch_width = 2 switch_height = 0.5 overlen_top = 1 overlen_bottom = 1 ddrill = 0 pad_smd = [1.2, 0.5] for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, ["Copal_CVS"], "Buttons_Switches_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True, [0.7, 0.7], 0.2, 0) # Omron A6H DIP-switches (https://www.omron.com/ecb/products/pdf/en-a6h.pdf): pins = [4,8,12,16,20] rm = 1.27 pinrow_distance = 6.15 package_width = 4.5 switch_width = 3.2 switch_height = 0.5 overlen_top = 1.27 overlen_bottom = 1.27 ddrill = 0 pad_smd = [1.25, 0.76] for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, ["Omron_A6H"], "Buttons_Switches_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True) # Copal CHS DIP-switches (http://www.nidec-copal-electronics.com/e/catalog/switch/chs.pdf): pins = [2, 4, 8, 12, 16, 20] rm = 1.27 pinrow_distance = 5.08 pinrow_distanceB = 7.62 package_width = 5.4 switch_width = 3 switch_height = 0.5 overlen_top = 1.27 overlen_bottom = 1.27 ddrill = 0 pad_smd = [1.6, 0.76] for p in pins: makeDIPSwitch(p, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, ["Copal_CHS-A"], "Buttons_Switches_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True) makeDIPSwitch(p, rm, pinrow_distanceB, package_width, overlen_top, overlen_bottom, ddrill, pad_smd, switch_width, switch_height, 'Slide', True, ["Copal_CHS-B"], "Buttons_Switches_SMD", [0, 0, 0], [1, 1, 1], [0, 0, 0], "", True) # # Special DIP # # http://www.experimentalistsanonymous.com/diy/Datasheets/MN3005.pdf # # common settings overlen_top=1.27 overlen_bottom=1.27 rm=2.54 ddrill=0.8 pad=[1.6,1.6] pad_large=[2.4,1.6] pad_smdsocket=[3.1,1.6] pad_smdsocket_small=[1.6,1.6] # narrow 7.62 DIPs pins=[8] pinrow_distance=7.62 package_width=6.35 socket_width=pinrow_distance+2.54 makeDIP(16, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, False, 0, 0, 0, prefix_name = '8', skip_pin = [3, 4, 5, 6, 11, 12, 13, 14], skip_count = True, right_cnt_start = 5) socket_height = (p / 2 - 1) * rm + 2.54 makeDIP(16, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, False, socket_width, socket_height,0, ["Socket"], prefix_name = '8', skip_pin = [3, 4, 5, 6, 11, 12, 13, 14], skip_count = True, right_cnt_start = 5) makeDIP(16, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad_large, False, socket_width, socket_height,0, ["Socket","LongPads"], prefix_name = '8', skip_pin = [3, 4, 5, 6, 11, 12, 13, 14], skip_count = True, right_cnt_start = 5) ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/Readme.md ================================================ # IPC gullwing generator This generator uses IPC-7351B equations and fillet definitions to derive a footprint for gullwing style packages from the dimensions of the package. (The suggested footprint is generally ignored. It is only used to define the exposed pad if necessary to fulfill thermal or EMC requirements defined in the datasheet.) Fillet size definitions can be changed by pointing to a personalized IPC parameter file. The script generates footprints in zero orientation version A (pin 1 at top left corner). Pads are generated using rounded rectangle pads as suggested in preliminary releases of IPC-7351C. Examples of supported packages include: QFP, SOIC, SO. ## Running the script The script requires python 3.4 or newer. Run it with: `python3 ipc_gullwing_generator.py size_definitions/eqfp.yaml` (replace `eqfp.yaml` with the size definition file that contains your part.) ### Optional script parameters * --global_config: the config file defining how the footprint will look like. (KLC) (default=`../../tools/global_config_files/config_KLCv3.0.yaml`) * --series_config: the config file defining series parameters (footprint naming). (default=`../package_config_KLCv3.yaml`) * --density: IPC density level (L,N,M) (default=`N`) * --ipc_doc: IPC definition document (default=`../ipc_definitions.yaml`) * --force_rectangle_pads: Force the generation of rectangle pads instead of rounded rectangle * --kicad4_compatible: Create footprints compatible with version 4 (avoids round-rect and custom pads). ## Size definition format Every file contains a header with parameters applied to all parts. These define the common footprint name prefix and the output library. ``` yaml FileHeader: library_Suffix: 'QFP' #resulting library name Package_QFP device_type: 'EQFP' #footprint names will be of style ...EQFP-pincount_... ``` --- Every further entry in the script is assumed to be a package size definition. The top level parameter will give the internal parameter set name. It must be unique in this file and should be representative of the footprint as it will be used in error messages. (It also makes later maintenance easier if it is easy to determine which footprint was generated by which parameter set.) ``` yaml internal_package_name: # parameter list (See below) ``` ### Documentation and naming parameters - Size source to be added to footprint documentation field (`size_source`) {url} - Footprint name generation control - Manufacturer name. Will be added as a prefix if given. (`manufacturer`) {string} - Part number. Will be added as a prefix if given. (`part_number`) {string} - Suffix: A custom suffix (added after pin pitch in default naming format). Can include parameters `pad_x` and `pad_y`. - Custom naming (`custom_name_format`) {python format string} - The full default format string is `{man:s}_{mpn:s}_{pkg:s}-{pincount:d}-1EP_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{suffix2:s}{vias:s}` (The same parameters can be used in your custom format. Exposed pad parameters are not available for components without exposed pad.) _Note: Contributions intended for the official library shall not include the manufacturer or part number unless the footprint is specific to that manufacturer or part. Similarly avoid custom naming for official library contributions unless required to achieve the requested name (Example TI-specific naming)._ ### Package dimensions ![dimension example](./documentation/dimension_system.svg) - Body size (`body_size_x`, `body_size_y`, `overall_height`) {dimension} - Lead dimensions: - Overall size representing lead tip to lead tip dimension (`overall_size_x`, `overall_size_y`) {dimension} - Lead width (`lead_width`) {dimension} - Lead length distance between the lead bend and lead tip (`lead_len`) {dimension} - Lead pitch, currently equal for all sides (`pitch`) {float} ### Pad count - Pad count (`num_pins_x`, `num_pins_y`) {int} - `num_pins_x`=0 is used for generating SOIC-like packages. - `num_pins_y`=0 is used to generate SOIC-like package footprints but with inverted pin numbering. (Mirrored numbering scheme. Some manufactures use this style in their datasheets. Make sure you are not looking at the bottom view before using this. Not supported for QFP and similar.) - Exclude pads by pad number (`exclude_pin_list`) {[`pad number`]} ### Exposed pad handling: ![exposed pad example](../documentation/ep_handling.svg) - Size of package exposed pad or slug (`EP_size_x`, `EP_size_y`) {dimension} - Size of the footprint pad [optional] (`EP_size_x_overwrite`, `EP_size_y_overwrite`) {float} - Pad size is equal to nominal package pad size if not given. - Use this to create a soldermask-defined pad. - Optional the size of the mask cutout (`EP_mask_x`, `EP_mask_y`) {float} - Use to create soldermask-defined pads (in combination with `EP_size_x_overwrite`) - Paste is split into a regular grid with (`EP_num_paste_pads`) {[int (x), int (y)]} - The optional paste coverage multiplier determines how much of the exposed copper area is covered by paste. (`EP_paste_coverage`) {float (0..1), default=0.65} ### Rounding of exposed pad features IPC excludes exposed pads from the requirement for rounding its corners. By default the exposed pad does therefore not use rounded corners. Some datasheets do however suggest the use of rounded corners either specified to a specific value or they appear to be equal to the normal pads. ![rounded exposed pad example](../documentation/ep_handling_rounded.svg) - Paste corner rounding is controlled by global config parameters `paste_radius_ratio` and `paste_maximum_radius` {float} - The round radius of the exposed pad can be directly set with `EP_round_radius` {float/"pad"} - The string "pad" can be used to force the same radius for the exposed pad as for the normal pads. - Alternatively the round radius ratio and max radius can be set using (`EP_round_radius_ratio`, `EP_maximum_radius`) {float} - Both these can be set per-footprint or in the global config file. ### Thermal vias A package with exposed pad can generate a version with thermal vias. This will be generated in addition to the normal version. ![exposed pad example](../documentation/thermal_vias.svg) ``` yaml thermal_vias: # thermal via version parameters ``` - Number of vias generated in the regular grid (`count`) {[int (x), int (y)]} - Final hole size (`drill`) {float} - Optional grid (`grid`) {[float (x), float (y)]} - Auto-generated if not given (outermost pad will touch pad edge). - Paste coverage overwrite [optional] (`EP_paste_coverage`) {float (0..1)} - Thermal via version might need higher paste coverage compared to non-via version to compensate solder lost due to wicking. - Paste generator can be set up to avoid placing paste on top of vias (`paste_avoid_via`) {bool} - Clearance between via hole and paste (`paste_via_clearance`) {float} - Can lead to math exceptions. Possible fixes: - Reduce paste coverage (make sure you still have enough paste) - Play with the via grid and number of paste pads (having an outer ring of paste pads often helps. This is only possible if there is space on the outside) - If no fix is satisfactory then select avoid vias as false and increase paste coverage to combat solder loss. - Number paste pads - Quantity of paste pads (`EP_num_paste_pads`) {[int (x), int (y)]} - Alternative available if `paste_avoid_via` is true - Number of paste pads between 4 vias (`paste_between_vias`) {[int (x), int (y)]} - Number of additional paste pad rings outside the outermost vias [optional] (`paste_rings_outside`) {[int (x), int (y)]} ## Dimension parameter format Dimensions in datasheets are either given with minimum and maximum value (optionally including nominal) or with the nominal value plus a tolerance. Some values of the datasheet are given as reference value without tolerance. (Tolerances in this measurement are already included in other dimensions.) The script reflects this by offering the same options. Always include the nominal dimension if the tolerance is asymmetrical as the resulting footprint will differ if it is not included. _Note: Contributions that are intended for the official KiCad library must use the same dimensioning format as the datasheet. (If min, nom and max are given then all 3 must be entered into the YAML file even if the tolerance is symmetrical. Similarly use nominal plus tolerance format if the datasheet is dimensioned this way.)_ ### String-based The parameter can be given as a string in one of the following formats (white space characters are ignored). ```yaml parameter_name: 1.2 # nominal only (reference dimension marked as such in datasheet) parameter_name: 1.1 .. 1.2 .. 1.3 # min .. nominal .. max parameter_name: 1.1 .. 1.3 # min .. max parameter_name: 1.2 +/-0.1 # nominal plus symmetrical tolerance parameter_name: 1.2 +0.1 -0.05 # nominal plus asymmetrical tolerance ``` ### Dict-based ```yaml parameter_name: # nominal only nominal: 1.2 tolerance: 0 # optional to make it clear that this is the case parameter_name: # minimum maximum and nominal minimum: 1.1 nominal: 1.2 maximum: 1.3 parameter_name: # minimum maximum minimum: 1.1 maximum: 1.3 parameter_name: # nominal with symmetrical tolerance nominal: 1.2 tolerance: 0.1 parameter_name: # nominal with asymmetrical tolerance nominal: 1.2 tolerance: [-0.05, 0.1] # order does not matter, the sign is important. ``` ### Deprecated format Support for this format will be dropped in the future. This format only supports min, nom, max dimensioning. ```yaml parameter_name_min: 1.1 parameter_name: 1.2 parameter_name_max: 1.3 ``` ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/ipc_gullwing_generator.py ================================================ #!/usr/bin/env python3 import sys import os import argparse import yaml import math sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from ipc_pad_size_calculators import * from quad_dual_pad_border import add_dual_or_quad_pad_border from drawing_tools import nearestSilkPointOnOrthogonalLine sys.path.append(os.path.join(sys.path[0], "..", "utils")) from ep_handling_utils import getEpRoundRadiusParams ipc_density = 'nominal' ipc_doc_file = '../ipc_definitions.yaml' DEFAULT_PASTE_COVERAGE = 0.65 DEFAULT_VIA_PASTE_CLEARANCE = 0.15 DEFAULT_MIN_ANNULAR_RING = 0.15 def roundToBase(value, base): return round(value/base) * base class Gullwing(): def __init__(self, configuration): self.configuration = configuration with open(ipc_doc_file, 'r') as ipc_stream: try: self.ipc_defintions = yaml.safe_load(ipc_stream) self.configuration['min_ep_to_pad_clearance'] = 0.2 #ToDo: find a settings file that can contain these. self.configuration['paste_radius_ratio'] = 0.25 self.configuration['paste_maximum_radius'] = 0.25 if 'ipc_generic_rules' in self.ipc_defintions: self.configuration['min_ep_to_pad_clearance'] = self.ipc_defintions['ipc_generic_rules'].get('min_ep_to_pad_clearance', 0.2) except yaml.YAMLError as exc: print(exc) def calcPadDetails(self, device_dimensions, EP_size, ipc_data, ipc_round_base): # Zmax = Lmin + 2JT + √(CL^2 + F^2 + P^2) # Gmin = Smax − 2JH − √(CS^2 + F^2 + P^2) # Xmax = Wmin + 2JS + √(CW^2 + F^2 + P^2) # Some manufacturers do not list the terminal spacing (S) in their datasheet but list the terminal lenght (T) # Then one can calculate # Stol(RMS) = √(Ltol^2 + 2*^2) # Smin = Lmin - 2*Tmax # Smax(RMS) = Smin + Stol(RMS) manf_tol = { 'F': self.configuration.get('manufacturing_tolerance', 0.1), 'P': self.configuration.get('placement_tolerance', 0.05) } Gmin_x, Zmax_x, Xmax = ipc_gull_wing( ipc_data, ipc_round_base, manf_tol, device_dimensions['lead_width'], device_dimensions['overall_size_x'], lead_len=device_dimensions.get('lead_len'), heel_reduction=device_dimensions.get('heel_reduction', 0) ) Gmin_y, Zmax_y, Xmax_y_ignored = ipc_gull_wing( ipc_data, ipc_round_base, manf_tol, device_dimensions['lead_width'], device_dimensions['overall_size_y'], lead_len=device_dimensions.get('lead_len'), heel_reduction=device_dimensions.get('heel_reduction', 0) ) min_ep_to_pad_clearance = configuration['min_ep_to_pad_clearance'] heel_reduction_max = 0 if Gmin_x - 2*min_ep_to_pad_clearance < EP_size['x']: heel_reduction_max = ((EP_size['x'] + 2*min_ep_to_pad_clearance - Gmin_x)/2) #print('{}, {}, {}'.format(Gmin_x, EP_size['x'], min_ep_to_pad_clearance)) Gmin_x = EP_size['x'] + 2*min_ep_to_pad_clearance if Gmin_y - 2*min_ep_to_pad_clearance < EP_size['y']: heel_reduction = ((EP_size['y'] + 2*min_ep_to_pad_clearance - Gmin_y)/2) if heel_reduction>heel_reduction_max: heel_reduction_max = heel_reduction Gmin_y = EP_size['y'] + 2*min_ep_to_pad_clearance Pad = {} Pad['left'] = {'center':[-(Zmax_x+Gmin_x)/4, 0], 'size':[(Zmax_x-Gmin_x)/2,Xmax]} Pad['right'] = {'center':[(Zmax_x+Gmin_x)/4, 0], 'size':[(Zmax_x-Gmin_x)/2,Xmax]} Pad['top'] = {'center':[0,-(Zmax_y+Gmin_y)/4], 'size':[Xmax,(Zmax_y-Gmin_y)/2]} Pad['bottom'] = {'center':[0,(Zmax_y+Gmin_y)/4], 'size':[Xmax,(Zmax_y-Gmin_y)/2]} return Pad @staticmethod def deviceDimensions(device_size_data): dimensions = { 'body_size_x': TolerancedSize.fromYaml(device_size_data, base_name='body_size_x'), 'body_size_y': TolerancedSize.fromYaml(device_size_data, base_name='body_size_y'), 'lead_width': TolerancedSize.fromYaml(device_size_data, base_name='lead_width'), 'lead_len': TolerancedSize.fromYaml(device_size_data, base_name='lead_len') } dimensions['has_EP'] = False if 'EP_size_x_min' in device_size_data and 'EP_size_x_max' in device_size_data or 'EP_size_x' in device_size_data: dimensions['EP_size_x'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_size_x') dimensions['EP_size_y'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_size_y') dimensions['has_EP'] = True if 'EP_mask_x' in device_size_data: dimensions['EP_mask_x'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_mask_x') dimensions['EP_mask_y'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_mask_y') dimensions['heel_reduction'] = device_size_data.get('heel_reduction', 0) if 'overall_size_x' in device_size_data or 'overall_size_y' in device_size_data: if 'overall_size_x' in device_size_data: dimensions['overall_size_x'] = TolerancedSize.fromYaml(device_size_data, base_name='overall_size_x') else: dimensions['overall_size_x'] = TolerancedSize.fromYaml(device_size_data, base_name='overall_size_y') if 'overall_size_y' in device_size_data: dimensions['overall_size_y'] = TolerancedSize.fromYaml(device_size_data, base_name='overall_size_y') else: dimensions['overall_size_y'] = TolerancedSize.fromYaml(device_size_data, base_name='overall_size_x') else: raise KeyError("Either overall size x or overall size y must be given (Outside to outside lead dimensions)") return dimensions def generateFootprint(self, device_params, header): dimensions = Gullwing.deviceDimensions(device_params) if 'deleted_pins' in device_params: if type(device_params['deleted_pins']) is int: device_params['deleted_pins'] = [device_params['deleted_pins']] if 'hidden_pins' in device_params: if type(device_params['hidden_pins']) is int: device_params['hidden_pins'] = [device_params['hidden_pins']] if 'deleted_pins' in device_params and 'hidden_pins' in device_params: print("A footprint may not have deleted pins and hidden pins.") else: if dimensions['has_EP'] and 'thermal_vias' in device_params: self.__createFootprintVariant(device_params, header, dimensions, True) self.__createFootprintVariant(device_params, header, dimensions, False) def __createFootprintVariant(self, device_params, header, dimensions, with_thermal_vias): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = self.configuration['lib_name_format_string'].format(category=header['library_Suffix']) size_x = dimensions['body_size_x'].nominal size_y = dimensions['body_size_y'].nominal pincount_full = device_params['num_pins_x']*2 + device_params['num_pins_y']*2 if 'hidden_pins' in device_params: pincount_text = '{}-{}'.format(pincount_full - len(device_params['hidden_pins']), pincount_full) pincount = pincount_full - len(device_params['hidden_pins']) elif 'deleted_pins' in device_params: pincount_text = '{}-{}'.format(pincount_full, pincount_full - len(device_params['deleted_pins'])) pincount = pincount_full - len(device_params['deleted_pins']) else: pincount_text = '{}'.format(pincount_full) pincount = pincount_full ipc_reference = 'ipc_spec_gw_large_pitch' if device_params['pitch'] >= 0.625 else 'ipc_spec_gw_small_pitch' if device_params.get('force_small_pitch_ipc_definition', False): ipc_reference = 'ipc_spec_gw_small_pitch' used_density = device_params.get('ipc_density', ipc_density) ipc_data_set = self.ipc_defintions[ipc_reference][used_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pitch = device_params['pitch'] name_format = self.configuration['fp_name_format_string_no_trailing_zero_pincount_text'] EP_size = {'x':0, 'y':0} EP_mask_size = {'x':0, 'y':0} if dimensions['has_EP']: name_format = self.configuration['fp_name_EP_format_string_no_trailing_zero_pincount_text'] if 'EP_size_x_overwrite' in device_params: EP_size = { 'x':device_params['EP_size_x_overwrite'], 'y':device_params['EP_size_y_overwrite'] } else: EP_size = { 'x':dimensions['EP_size_x'].nominal, 'y':dimensions['EP_size_y'].nominal } if 'EP_mask_x' in dimensions: name_format = self.configuration['fp_name_EP_custom_mask_format_string_no_trailing_zero_pincount_text'] EP_mask_size = {'x':dimensions['EP_mask_x'].nominal, 'y':dimensions['EP_mask_y'].nominal} EP_size = Vector2D(EP_size) pad_details = self.calcPadDetails(dimensions, EP_size, ipc_data_set, ipc_round_base) if 'custom_name_format' in device_params: name_format = device_params['custom_name_format'] suffix = device_params.get('suffix', '').format(pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix','${KISYS3DMOD}') fp_name = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=header['device_type'], pincount=pincount_text, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], ep_size_x = EP_size['x'], ep_size_y = EP_size['y'], mask_size_x = EP_mask_size['x'], mask_size_y = EP_mask_size['y'], suffix=suffix, suffix2="", vias=self.configuration.get('thermal_via_suffix', '_ThermalVias') if with_thermal_vias else '' ).replace('__','_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=header['device_type'], pincount=pincount_text, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], ep_size_x = EP_size['x'], ep_size_y = EP_size['y'], mask_size_x = EP_mask_size['x'], mask_size_y = EP_mask_size['y'], suffix=suffix_3d, suffix2="", vias='' ).replace('__','_').lstrip('_') model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = header['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=header['device_type'], category=header['library_Suffix'] ).lstrip()) kicad_mod.setAttribute('smd') if 'custom_pad_layout' in device_params: pad_radius = add_custom_pad_layout(kicad_mod, configuration, pad_details, device_params) else: pad_radius = add_dual_or_quad_pad_border(kicad_mod, configuration, pad_details, device_params) EP_round_radius = 0 if dimensions['has_EP']: pad_shape_details = getEpRoundRadiusParams(device_params, self.configuration, pad_radius) EP_mask_size = EP_mask_size if EP_mask_size['x'] > 0 else None if with_thermal_vias: thermals = device_params['thermal_vias'] paste_coverage = thermals.get('EP_paste_coverage', device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE)) EP = ExposedPad( number=pincount+1, size=EP_size, mask_size=EP_mask_size, paste_layout=thermals.get('EP_num_paste_pads'), paste_coverage=paste_coverage, via_layout=thermals.get('count', 0), paste_between_vias=thermals.get('paste_between_vias'), paste_rings_outside=thermals.get('paste_rings_outside'), via_drill=thermals.get('drill', 0.3), via_grid=thermals.get('grid'), paste_avoid_via=thermals.get('paste_avoid_via', True), via_paste_clarance=thermals.get('paste_via_clearance', DEFAULT_VIA_PASTE_CLEARANCE), min_annular_ring=thermals.get('min_annular_ring', DEFAULT_MIN_ANNULAR_RING), bottom_pad_min_size=thermals.get('bottom_min_size', 0), **pad_shape_details ) else: EP = ExposedPad( number=pincount+1, size=EP_size, mask_size=EP_mask_size, paste_layout=device_params.get('EP_num_paste_pads', 1), paste_coverage=device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE), **pad_shape_details ) kicad_mod.append(EP) EP_round_radius = EP.getRoundRadius() body_edge = { 'left': -dimensions['body_size_x'].nominal/2, 'right': dimensions['body_size_x'].nominal/2, 'top': -dimensions['body_size_y'].nominal/2, 'bottom': dimensions['body_size_y'].nominal/2 } bounding_box = { 'left': pad_details['left']['center'][0] - pad_details['left']['size'][0]/2, 'right': pad_details['right']['center'][0] + pad_details['right']['size'][0]/2, 'top': pad_details['top']['center'][1] - pad_details['top']['size'][1]/2, 'bottom': pad_details['bottom']['center'][1] + pad_details['bottom']['size'][1]/2 } if device_params['num_pins_x'] == 0: bounding_box['top'] = body_edge['top'] bounding_box['bottom'] = body_edge['bottom'] if EP_size['y'] > dimensions['body_size_y'].nominal: bounding_box['top'] = -EP_size['y']/2 bounding_box['bottom'] = EP_size['y']/2 if device_params['num_pins_y'] == 0: bounding_box['left'] = body_edge['left'] bounding_box['right'] = body_edge['right'] if EP_size['x'] > dimensions['body_size_x'].nominal: bounding_box['left'] = -EP_size['x']/2 bounding_box['right'] = EP_size['x']/2 pad_width = pad_details['top']['size'][0] # ############################ SilkS ################################## silk_pad_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 silk_offset = configuration['silk_fab_offset'] right_pads_silk_bottom = (device_params['num_pins_y']-1)*device_params['pitch']/2\ +pad_details['right']['size'][1]/2+silk_pad_offset silk_bottom = body_edge['bottom']+silk_offset if EP_size['y']/2 <= body_edge['bottom'] and right_pads_silk_bottom >= silk_bottom: silk_bottom = max(silk_bottom, EP_size['y']/2+silk_pad_offset) silk_bottom = max(silk_bottom, right_pads_silk_bottom) silk_bottom = min(body_edge['bottom']+silk_pad_offset, silk_bottom) bottom_pads_silk_right = (device_params['num_pins_x']-1)*device_params['pitch']/2\ +pad_details['bottom']['size'][0]/2+silk_pad_offset silk_right = body_edge['right']+silk_offset if EP_size['x']/2 <= body_edge['right'] and bottom_pads_silk_right >= silk_right: silk_right = max(silk_right, EP_size['x']/2+silk_pad_offset) silk_right = max(silk_right, bottom_pads_silk_right) silk_right = min(body_edge['right']+silk_pad_offset, silk_right) min_lenght = configuration.get('silk_line_lenght_min', 0) silk_corner_bottom_right = Vector2D(silk_right, silk_bottom) silk_point_bottom_inside = nearestSilkPointOnOrthogonalLine( pad_size=EP_size, pad_position=[0, 0], pad_radius=EP_round_radius, fixed_point=silk_corner_bottom_right, moving_point=Vector2D(0, silk_bottom), silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_bottom_inside is not None and device_params['num_pins_x'] > 0: silk_point_bottom_inside = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['bottom']['size'], pad_position=[ pad_details['bottom']['center'][0]+(device_params['num_pins_x']-1)/2*pitch, pad_details['bottom']['center'][1]], pad_radius=pad_radius, fixed_point=silk_corner_bottom_right, moving_point=silk_point_bottom_inside, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) silk_point_right_inside = nearestSilkPointOnOrthogonalLine( pad_size=EP_size, pad_position=[0, 0], pad_radius=EP_round_radius, fixed_point=silk_corner_bottom_right, moving_point=Vector2D(silk_right, 0), silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_right_inside is not None and device_params['num_pins_y'] > 0: silk_point_right_inside = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['right']['size'], pad_position=[ pad_details['right']['center'][0], pad_details['right']['center'][1]+(device_params['num_pins_y']-1)/2*pitch], pad_radius=pad_radius, fixed_point=silk_corner_bottom_right, moving_point=silk_point_right_inside, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) if silk_point_bottom_inside is None and silk_point_right_inside is not None: silk_corner_bottom_right['y'] = body_edge['bottom'] silk_corner_bottom_right = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['bottom']['size'], pad_position=[ pad_details['bottom']['center'][0]+(device_params['num_pins_x']-1)/2*pitch, pad_details['bottom']['center'][1]], pad_radius=pad_radius, fixed_point=silk_point_right_inside, moving_point=silk_corner_bottom_right, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) elif silk_point_right_inside is None and silk_point_bottom_inside is not None: silk_corner_bottom_right['x'] = body_edge['right'] silk_corner_bottom_right = nearestSilkPointOnOrthogonalLine( pad_size=pad_details['right']['size'], pad_position=[ pad_details['right']['center'][0], pad_details['right']['center'][1]+(device_params['num_pins_y']-1)/2*pitch], pad_radius=pad_radius, fixed_point=silk_point_bottom_inside, moving_point=silk_corner_bottom_right, silk_pad_offset=silk_pad_offset, min_lenght=min_lenght) poly_bottom_right = [] if silk_point_bottom_inside is not None: poly_bottom_right.append(silk_point_bottom_inside) poly_bottom_right.append(silk_corner_bottom_right) if silk_point_right_inside is not None: poly_bottom_right.append(silk_point_right_inside) if len(poly_bottom_right) > 1 and silk_corner_bottom_right is not None: kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) if device_params['num_pins_y'] > 0: if len(poly_bottom_right)>2: kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0, x_mirror=0)) kicad_mod.append(Line( start={'x': -silk_right, 'y': -right_pads_silk_bottom}, end={'x': bounding_box['left'], 'y': -right_pads_silk_bottom}, width=configuration['silk_line_width'], layer="F.SilkS")) elif silk_corner_bottom_right['y'] >= right_pads_silk_bottom and silk_point_bottom_inside is not None: kicad_mod.append(Line( start=-silk_point_bottom_inside, end={'x': bounding_box['left'], 'y': -silk_point_bottom_inside['y']}, width=configuration['silk_line_width'], layer="F.SilkS")) else: if len(poly_bottom_right)>2: poly_bottom_right[0]['x']=bottom_pads_silk_right kicad_mod.append(PolygoneLine( polygone=poly_bottom_right, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0, x_mirror=0)) kicad_mod.append(Line( start={'x': -bottom_pads_silk_right, 'y': -silk_corner_bottom_right['y']}, end={'x': -bottom_pads_silk_right, 'y': bounding_box['top']}, width=configuration['silk_line_width'], layer="F.SilkS")) elif silk_corner_bottom_right['x'] >= bottom_pads_silk_right and silk_point_right_inside is not None: kicad_mod.append(Line( start=-silk_point_right_inside, end={'x': -silk_point_right_inside['x'], 'y': bounding_box['top']}, width=configuration['silk_line_width'], layer="F.SilkS")) # # ######################## Fabrication Layer ########################### fab_bevel_size = min(configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative']*min(size_x, size_y)) poly_fab = [ {'x': body_edge['left']+fab_bevel_size, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']+fab_bevel_size}, {'x': body_edge['left']+fab_bevel_size, 'y': body_edge['top']}, ] kicad_mod.append(PolygoneLine( polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] if device_params['num_pins_y'] == 0 or device_params['num_pins_x'] == 0: cy1=roundToBase(bounding_box['top']-off, grid) kicad_mod.append(RectLine( start={ 'x':roundToBase(bounding_box['left']-off, grid), 'y':cy1 }, end={ 'x':roundToBase(bounding_box['right']+off, grid), 'y':roundToBase(bounding_box['bottom']+off, grid) }, width=configuration['courtyard_line_width'], layer='F.CrtYd')) else: cy1=roundToBase(bounding_box['top']-off, grid) cy2=roundToBase(body_edge['top']-off, grid) cy3=-roundToBase( device_params['pitch']*(device_params['num_pins_y']-1)/2.0 + pad_width/2.0 + off, grid) cx1=-roundToBase( device_params['pitch']*(device_params['num_pins_x']-1)/2.0 + pad_width/2.0 + off, grid) cx2=roundToBase(body_edge['left']-off, grid) cx3=roundToBase(bounding_box['left']-off, grid) crty_poly_tl = [ {'x':0, 'y':cy1}, {'x':cx1, 'y':cy1}, {'x':cx1, 'y':cy2}, {'x':cx2, 'y':cy2}, {'x':cx2, 'y':cy3}, {'x':cx3, 'y':cy3}, {'x':cx3, 'y':0} ] kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'])) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], y_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0, y_mirror=0)) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top': cy1, 'bottom': -cy1}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints. See readme.md for details about the parameter file format.') parser.add_argument('files', metavar='file', type=str, nargs='+', help='list of files holding information about what devices should be created.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../package_config_KLCv3.yaml') parser.add_argument('--density', type=str, nargs='?', help='IPC density level (L,N,M)', default='N') parser.add_argument('--ipc_doc', type=str, nargs='?', help='IPC definition document', default='../ipc_definitions.yaml') parser.add_argument('--force_rectangle_pads', action='store_true', help='Force the generation of rectangle pads instead of rounded rectangle') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints compatible with version 4 (avoids round-rect and custom pads).') args = parser.parse_args() if args.density == 'L': ipc_density = 'least' elif args.density == 'M': ipc_density = 'most' ipc_doc_file = args.ipc_doc with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) if args.force_rectangle_pads or args.kicad4_compatible: configuration['round_rect_max_radius'] = None configuration['round_rect_radius_ratio'] = 0 configuration['kicad4_compatible'] = args.kicad4_compatible for filepath in args.files: gw = Gullwing(configuration) with open(filepath, 'r') as command_stream: try: cmd_file = yaml.safe_load(command_stream) except yaml.YAMLError as exc: print(exc) header = cmd_file.pop('FileHeader') for pkg in cmd_file: print("generating part for parameter set {}".format(pkg)) gw.generateFootprint(cmd_file[pkg], header) ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/eqfp.yaml ================================================ FileHeader: library_Suffix: 'QFP' device_type: 'EQFP' EQFP-144-1EP_20x20mm_P0.5mm_EP4x4mm: size_source: 'https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/packaging/04r00482-02.pdf' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.5 num_pins_x: 36 num_pins_y: 36 EP_size_x: 4 EP_size_y: 4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.2, 1.2] # bottom_pad_size: # paste_avoid_via: True EQFP-144-1EP_20x20mm_P0.5mm_EP5x5mm: size_source: 'https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/packaging/04r00476-02.pdf' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.5 num_pins_x: 36 num_pins_y: 36 EP_size_x: 5 EP_size_y: 5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.2, 1.2] # bottom_pad_size: # paste_avoid_via: True EQFP-144-1EP_20x20mm_P0.5mm_EP6.61x5.615mm: size_source: 'https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/packaging/04r00485-02.pdf' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.5 num_pins_x: 36 num_pins_y: 36 EP_size_x: 6.61 EP_size_y: 5.615 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 4] thermal_vias: count: [5, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.3, 1.4] # bottom_pad_size: # paste_avoid_via: True EQFP-144-1EP_20x20mm_P0.5mm_EP7.2x6.35mm: size_source: 'https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/packaging/04r00487-01.pdf' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.5 num_pins_x: 36 num_pins_y: 36 EP_size_x: 7.2 EP_size_y: 6.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [6, 5] thermal_vias: count: [6, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.2, 1.2] # bottom_pad_size: # paste_avoid_via: True EQFP-144-1EP_20x20mm_P0.5mm_EP8.93x8.7mm: size_source: 'https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/packaging/04r00479-02.pdf' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.5 num_pins_x: 36 num_pins_y: 36 EP_size_x: 8.93 EP_size_y: 8.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [7, 7] thermal_vias: count: [7, 7] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.2, 1.2] # bottom_pad_size: # paste_avoid_via: True ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/hsoic.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'HSOIC' Texas_R-PDSO-G8_EP2.95x4.9mm_Mask2.4x3.1mm: size_source: 'http://www.ti.com/lit/ds/symlink/lmr14030.pdf#page=28, http://www.ti.com/lit/ml/msoi002j/msoi002j.pdf' custom_name_format: 'Texas_R-PDSO-G{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{vias:s}' body_size_x: minimum: 3.8 maximum: 4 body_size_y: minimum: 4.8 maximum: 5 overall_size_x: minimum: 5.8 maximum: 6.2 lead_width: minimum: 0.31 maximum: 0.51 lead_len: minimum: 0.4 maximum: 1.27 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: minimum: 1.65 maximum: 2.4 EP_size_x_overwrite: 2.95 EP_mask_x: 2.4 EP_size_y: minimum: 2.65 maximum: 3.1 EP_size_y_overwrite: 4.9 EP_mask_y: 3.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 3] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/hsop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'HSOP' HSOP-8-1EP_3.9x4.9mm_P1.27mm_EP2.41x3.1mm_ThermalVias: size_source: 'https://www.st.com/resource/en/datasheet/l5973d.pdf' body_size_x: nominal: 3.9 tolerance: 0.1 body_size_y: nominal: 4.9 tolerance: 0.1 overall_size_x: nominal: 6 tolerance: 0.2 lead_width: nominal: 0.42 tolerance: [0.04, 0.05] lead_len: nominal: 0.65 tolerance: 0.15 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 2.41 tolerance: 0.1 EP_size_y: nominal: 3.1 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.65 # grid: [1.5, 1.5] # bottom_pad_size: paste_avoid_via: False HSOP-8-1EP_3.9x4.9mm_P1.27mm_EP2.3x2.3mm_ThermalVias: size_source: 'https://www.st.com/resource/en/datasheet/l7980.pdf' body_size_x: nominal: 3.9 tolerance: 0.1 body_size_y: nominal: 4.9 tolerance: 0.1 overall_size_x: nominal: 6 tolerance: 0.2 lead_width: minimum: 0.31 maximum: 0.51 lead_len: minimum: 0.40 maximum: 1.27 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 2.3 EP_size_y: nominal: 2.3 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.65 # grid: [1.5, 1.5] # bottom_pad_size: paste_avoid_via: False ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/htsop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'HTSOP' HTSOP-8-1EP_3.9x4.9mm_P1.27mm_EP2.4x3.2mm: size_source: 'https://media.digikey.com/pdf/Data%20Sheets/Rohm%20PDFs/BD9G341EFJ.pdf' body_size_x: nominal: 3.9 tolerance: 0.1 body_size_y: nominal: 4.9 tolerance: 0.1 overall_size_x: nominal: 6 tolerance: 0.2 lead_width: nominal: 0.42 tolerance: [0.04, 0.05] lead_len: nominal: 0.65 tolerance: 0.15 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: 2.4 EP_size_y: 3.2 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.65 # grid: [1.5, 1.5] # bottom_pad_size: paste_avoid_via: False ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/htssop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'HTSSOP' HTSSOP-16-1EP_4.4x5mm_P0.65mm_EP3x3mm: size_source: 'https://www.st.com/resource/en/datasheet/stp08cp05.pdf#page=20' body_size_x: minimum: 4.3 nominal: 4.4 maximum: 4.5 body_size_y: minimum: 4.9 nominal: 5 maximum: 5.1 body_height: maximum: 1.2 overall_size_x: minimum: 6.2 nominal: 6.4 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 EP_size_x: nominal: 3 EP_size_y: nominal: 3 EP_num_paste_pads: [2, 2] HTSSOP-16-1EP_4.4x5mm_P0.65mm_EP3.4x5mm_Mask2.46x2.31mm_ThermalVias: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 4.9 maximum: 5.1 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 EP_size_x: nominal: 3.4 EP_size_y: nominal: 5 EP_mask_x: 2.46 EP_mask_y: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [1, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.5, 1.5] # bottom_pad_size: paste_avoid_via: False HTSSOP-20-1EP_4.4x6.5mm_P0.65mm_EP3.4x6.5mm_Mask2.4x3.7mm: size_source: 'http://www.ti.com/lit/ds/symlink/bq24006.pdf' body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 6.4 maximum: 6.6 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 10 EP_size_x: nominal: 3.4 EP_size_y: nominal: 6.5 EP_mask_x: 2.4 EP_mask_y: 3.7 EP_num_paste_pads: [1, 2] HTSSOP-20-1EP_4.4x6.5mm_P0.65mm_EP2.85x4mm: size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0108.PDF U20E-1' body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 6.4 maximum: 6.6 body_height: maximum: 1.1 overall_size_x: minimum: 6.25 maximum: 6.5 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.7 pitch: 0.65 num_pins_x: 0 num_pins_y: 10 EP_size_x: minimum: 2.6 maximum: 3.1 EP_size_y: minimum: 3.8 maximum: 4.2 EP_num_paste_pads: [1, 2] HTSSOP-24-1EP_4.4x7.8mm_P0.65mm_EP3.2x5mm: size_source: 'https://www.st.com/resource/en/datasheet/stp16cp05.pdf#page=25' body_size_x: minimum: 4.3 nominal: 4.4 maximum: 4.5 body_size_y: minimum: 7.7 nominal: 7.8 maximum: 7.9 body_height: maximum: 1.2 overall_size_x: minimum: 6.2 nominal: 6.4 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 12 EP_size_x: minimum: 3 nominal: 3.2 maximum: 3.4 EP_size_y: minimum: 4.8 nominal: 5 maximum: 5.2 EP_num_paste_pads: [2, 3] HTSSOP-24-1EP_4.4x7.8mm_P0.65mm_EP3.4x7.8mm_Mask2.4x4.68mm_ThermalVias: size_source: 'http://www.ti.com/lit/ds/symlink/tps703.pdf' body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 7.7 maximum: 7.9 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 12 EP_size_x: 3.4 EP_size_y: 7.8 EP_mask_x: 2.4 EP_mask_y: 4.68 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 6] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [1, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False HTSSOP-28-1EP_4.4x9.7mm_P0.65mm_EP2.85x5.4mm: size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0108.PDF' body_size_x: 4.3 .. 4.5 body_size_y: 9.6 .. 9.8 overall_height: maximum: 1.1 overall_size_x: 6.25 .. 6.5 lead_width: 0.19 .. 0.3 lead_len: 0.5 .. 0.7 pitch: 0.65 num_pins_x: 0 num_pins_y: 14 EP_size_x: 2.6 .. 3.1 EP_size_y: 5.2 .. 5.6 thermal_vias: count: [2, 4] drill: 0.3 paste_avoid_via: false EP_num_paste_pads: [1, 3] HTSSOP-44_6.1x14.0mm_P0.5mm_TopEP4.14x7.01mm: size_source: 'http://www.ti.com/lit/ds/symlink/tpa3251.pdf#page=38' custom_name_format: 'HTSSOP-{pincount}_{size_x:g}x{size_y:g}mm_P{pitch}mm_TopEP4.14x7.01mm' body_size_x: minimum: 6.0 maximum: 6.2 body_size_y: minimum: 13.9 maximum: 14.1 overall_size_y: minimum: 7.9 maximum: 8.3 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.635 num_pins_y: 22 num_pins_x: 0 #top_heatsink: #x: 4.14 #y: 7.01 Texas_PWP_R-PDSO-G14: # HTSSOP-14-1EP_4.4x5.0mm_P0.65mm_EP3.4x5.0mm_Mask3.0x3.1mm: size_source: 'http://www.ti.com/lit/ds/symlink/lm5161.pdf#page=34' # HTSSOP-14- 1EP_4.4x5.0 mm_P0.65 mm_EP3.4x5.0 mm_Mask3.0x3.1mm: custom_name_format: 'HTSSOP-{pincount}-1EP_{size_x:g}x{size_y:g}mm_P{pitch}mm_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{vias:s}' body_size_x: minimum: 4.3 nominal: 4.4 maximum: 4.5 body_size_y: minimum: 4.9 nominal: 5.0 maximum: 5.1 overall_size_x: minimum: 6.2 nominal: 6.4 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 7 EP_size_x: 3.4 EP_size_y: 5.0 EP_mask_x: 3.0 EP_mask_y: 3.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 5] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False Texas_PWP_R-PDSO-G20: # HTSSOP-20-1EP_4.4x6.5mm_P0.65mm_EP3.4x6.5mm_Mask2.75x3.43mm: size_source: 'http://www.ti.com/lit/ds/symlink/tlc5971.pdf#page=37&zoom=160,-90,3' # HTSSOP-20- 1EP_4.4x6.5 mm_P0.65 mm_EP3.4x6.5 mm_Mask2.75x3.43mm: custom_name_format: 'HTSSOP-{pincount}-1EP_{size_x:g}x{size_y:g}mm_P{pitch}mm_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{vias:s}' body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 6.4 maximum: 6.6 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 10 EP_size_x: 3.4 EP_size_y: 6.5 EP_mask_x: 2.75 EP_mask_y: 3.43 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 5] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False Texas_PWP0020T: # HTSSOP-20-1EP_4.4x6.5mm_P0.65mm_EP3.4x6.5mm_Mask2.96x2.96mm: size_source: 'https://www.ti.com/lit/ds/symlink/tps2663.pdf#page=49' # HTSSOP-20- 1EP_4.4x6.5 mm_P0.65 mm_EP3.4x6.5 mm_Mask2.96x2.96mm: custom_name_format: 'HTSSOP-{pincount}-1EP_{size_x:g}x{size_y:g}mm_P{pitch}mm_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{vias:s}' body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 6.4 maximum: 6.6 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 10 EP_size_x: 2.16 .. 2.96 EP_size_x_overwrite: 3.4 EP_size_y: 2.21 .. 2.96 EP_size_y_overwrite: 6.5 EP_mask_x: 2.96 EP_mask_y: 2.96 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 1] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 5] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False Texas_DAP_R-PDSO-G38: # HTSSOP-38-1EP_6.1x12.5mm_P0.65mm_EP5.2x12.5mm_Mask3.39x6.35mm size_source: 'http://www.ti.com/lit/ds/symlink/tlc5951.pdf#page=47&zoom=140,-67,15' # HTSSOP-38- 1EP_6.1x12.5 mm_P0.65 mm_EP5.2x12.5 mm_Mask3.39x6.35mm custom_name_format: 'HTSSOP-{pincount}-1EP_{size_x:g}x{size_y:g}mm_P{pitch}mm_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{vias:s}' body_size_x: minimum: 6.0 maximum: 6.2 body_size_y: minimum: 12.4 maximum: 12.6 overall_size_x: minimum: 7.9 maximum: 8.3 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 19 EP_size_x: 5.2 EP_size_y: 12.5 EP_mask_x: 3.39 EP_mask_y: 6.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 10] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 3] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/hvssop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'HVSSOP' HVSSOP-10-1EP_3x3mm_P0.5mm_EP1.57x1.88mm: size_source: 'https://www.ti.com/lit/ds/symlink/bq24090.pdf' body_size_x: nominal: 3 tolerance: 0.100 body_size_y: nominal: 3 tolerance: 0.100 overall_height: maximum: 1.1 overall_size_x: minimum: 4.75 maximum: 5.05 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.4 maximum: 0.7 pitch: 0.5 num_pins_x: 0 num_pins_y: 5 EP_size_x: nominal: 1.57 EP_size_y: nominal: 1.88 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] EP_num_paste_pads: [2, 2] paste_avoid_via: False ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/infineon.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'PG-DSO' Infineon_PG-DSO-8-27: size_source: 'https://www.infineon.com/cms/en/product/packages/PG-DSO/PG-DSO-8-27' manufacturer: Infineon custom_name_format: '{man}_PG-DSO-{pincount}-27_{size_x:g}x{size_y:g}mm_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: 3.9 +/-0.1 body_size_y: 4.9 +/-0.1 overall_height: maximum: 1.7 overall_size_x: 6.0 +/-0.2 lead_width: 0.41 +/-0.09 lead_len: 0.64 +/-0.25 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: 2.65 +/-0.2 EP_size_y: 3.0 +/-0.2 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 # grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/lqfp.yaml ================================================ FileHeader: library_Suffix: 'QFP' device_type: 'LQFP' LQFP-32_5x5mm_P0.5mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT401-1.pdf' body_size_x: minimum: 4.9 maximum: 5.1 body_size_y: minimum: 4.9 maximum: 5.1 overall_size_x: minimum: 6.85 maximum: 7.15 overall_size_y: minimum: 6.85 maximum: 7.15 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 8 num_pins_y: 8 LQFP-32_7x7mm_P0.8mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT358-1.pdf' body_size_x: minimum: 6.9 maximum: 7.1 body_size_y: minimum: 6.9 maximum: 7.1 overall_size_x: minimum: 8.85 maximum: 9.15 overall_size_y: minimum: 8.85 maximum: 9.15 lead_width: minimum: 0.3 maximum: 0.4 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.8 num_pins_x: 8 num_pins_y: 8 LQFP-36_7x7mm_P0.65mm: size_source: 'https://www.onsemi.com/pub/Collateral/561AV.PDF' # ipc_density: 'least' force_small_pitch_ipc_definition: True body_size_x: nominal: 7 tolerance: 0.1 body_size_y: nominal: 7 tolerance: 0.1 overall_size_x: nominal: 9 tolerance: 0.2 overall_size_y: nominal: 9 tolerance: 0.2 lead_width: nominal: 0.3 tolerance: 0.1 lead_len: nominal: 0.5 tolerance: 0.2 pitch: 0.65 num_pins_x: 9 num_pins_y: 9 LQFP-44_10x10mm_P0.8mm: size_source: 'https://www.nxp.com/files-static/shared/doc/package_info/98ASS23225W.pdf?&fsrch=1' body_size_x: nominal: 10 body_size_y: nominal: 10 overall_size_x: nominal: 12 overall_size_y: nominal: 12 lead_width: minimum: 0.3 maximum: 0.45 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.8 num_pins_x: 11 num_pins_y: 11 LQFP-48_7x7mm_P0.5mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/ltc2358-16.pdf' body_size_x: nominal: 7 body_size_y: nominal: 7 overall_size_x: nominal: 9 overall_size_y: nominal: 9 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 12 num_pins_y: 12 LQFP-48-1ep: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' body_size_x: nominal: 7 tolerance: 0 # minimum: # maximum: body_size_y: nominal: 7 tolerance: 0 overall_size_x: nominal: 9 tolerance: 0 overall_size_y: nominal: 9 tolerance: 0 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 12 num_pins_y: 12 EP_size_x_min: 3.5 EP_size_x: 3.6 EP_size_x_max: 3.7 EP_size_y_min: 3.5 EP_size_y: 3.6 EP_size_y_max: 3.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: True LQFP-52_10x10mm_P0.65mm: size_source: 'https://www.nxp.com/docs/en/package-information/98ARL10526D.pdf' # ipc_density: 'least' force_small_pitch_ipc_definition: True body_size_x: nominal: 10 body_size_y: nominal: 10 overall_size_x: nominal: 12 overall_size_y: nominal: 12 lead_width: nominal: 0.325 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.65 num_pins_x: 13 num_pins_y: 13 LQFP-52-1EP_10x10mm_P0.65mm_EP4.8x4.8mm: size_source: 'https://www.onsemi.com/pub/Collateral/848H-01.PDF' force_small_pitch_ipc_definition: True body_size_x: nominal: 10 tolerance: 0 body_size_y: nominal: 10 tolerance: 0 overall_size_x: nominal: 12 tolerance: 0 overall_size_y: nominal: 12 tolerance: 0 lead_width: minimum: 0.22 maximum: 0.4 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.65 num_pins_x: 13 num_pins_y: 13 EP_size_x: 4.8 EP_size_y: 4.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: True LQFP-52_14x14mm_P1mm: size_source: 'http://www.holtek.com/documents/10179/116711/HT1632Cv170.pdf' body_size_x: nominal: 14 minimum: 13.9 maximum: 14.1 body_size_y: nominal: 14 minimum: 13.9 maximum: 14.1 overall_size_x: nominal: 16 minimum: 15.8 maximum: 16.2 overall_size_y: nominal: 16 minimum: 15.8 maximum: 16.2 lead_width: minimum: 0.39 maximum: 0.48 lead_len: minimum: 0.45 maximum: 0.75 pitch: 1 num_pins_x: 13 num_pins_y: 13 LQFP-64-1EP_10x10mm_P0.5mm_EP6.5x6.5mm: size_source: 'https://www.nxp.com/files-static/shared/doc/package_info/98ARH98426A.pdf' # ipc_density: 'least' # force_small_pitch_ipc_definition: True body_size_x: nominal: 10 body_size_y: nominal: 10 overall_size_x: nominal: 12 overall_size_y: nominal: 12 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 16 num_pins_y: 16 EP_size_x: 6.5 EP_size_y: 6.5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 5] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.2, 1.2] # bottom_pad_size: # paste_avoid_via: True LQFP-64-1EP_10x10mm_P0.5mm_EP5.0x5.0mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/adv7611.pdf' # ipc_density: 'least' # force_small_pitch_ipc_definition: True body_size_x: nominal: 10 minimum: 9.8 maximum: 10.2 body_size_y: nominal: 10 minimum: 9.8 maximum: 10.2 overall_size_x: nominal: 12 minimum: 11.8 maximum: 12.2 overall_size_y: nominal: 12 minimum: 11.8 maximum: 12.2 lead_width: nominal: 0.22 minimum: 0.17 maximum: 0.27 lead_len: nominal: 0.6 minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 16 num_pins_y: 16 EP_size_x: nominal: 5.0 minimum: 4.9 maximum: 5.1 EP_size_y: nominal: 5.0 minimum: 4.9 maximum: 5.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 5] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.2, 1.2] # bottom_pad_size: # paste_avoid_via: True LQFP-64_7x7mm_P0.4mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT414-1.pdf' body_size_x: minimum: 6.9 maximum: 7.1 body_size_y: minimum: 6.9 maximum: 7.1 overall_size_x: minimum: 8.85 maximum: 9.15 overall_size_y: minimum: 8.85 maximum: 9.15 lead_width: minimum: 0.13 maximum: 0.23 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.4 num_pins_x: 16 num_pins_y: 16 LQFP-64_10x10mm_P0.5mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf' body_size_x: minimum: 9.8 nominal: 10 maximum: 10.2 body_size_y: minimum: 9.8 nominal: 10 maximum: 10.2 overall_size_x: minimum: 11.8 nominal: 12 maximum: 12.2 overall_size_y: minimum: 11.8 nominal: 12 maximum: 12.2 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.5 num_pins_x: 16 num_pins_y: 16 LQFP-64_14x14mm_P0.8mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT791-1.pdf' body_size_x: minimum: 13.9 maximum: 14.1 body_size_y: minimum: 13.9 maximum: 14.1 overall_size_x: minimum: 15.85 maximum: 16.15 overall_size_y: minimum: 15.85 maximum: 16.15 lead_width: minimum: 0.3 maximum: 0.45 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.8 num_pins_x: 16 num_pins_y: 16 LQFP-80_10x10mm_P0.4mm: size_source: 'https://www.renesas.com/eu/en/package-image/pdf/outdrawing/q80.10x10.pdf' body_size_x: nominal: 10 body_size_y: nominal: 10 overall_size_x: nominal: 12 overall_size_y: nominal: 12 lead_width: minimum: 0.13 nominal: 0.16 maximum: 0.23 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.4 num_pins_x: 20 num_pins_y: 20 LQFP-80_12x12mm_P0.5mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT315-1.pdf' body_size_x: minimum: 11.9 maximum: 12.1 body_size_y: minimum: 11.9 maximum: 12.1 overall_size_x: minimum: 13.85 maximum: 14.15 overall_size_y: minimum: 13.85 maximum: 14.15 lead_width: minimum: 0.13 maximum: 0.27 lead_len: minimum: 0.3 maximum: 0.75 pitch: 0.5 num_pins_x: 20 num_pins_y: 20 LQFP-80_14x14mm_P0.65mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/AD9852.pdf' force_small_pitch_ipc_definition: True body_size_x: minimum: 13.8 nominal: 14 maximum: 14.2 body_size_y: minimum: 13.8 nominal: 14 maximum: 14.2 overall_size_x: minimum: 15.8 nominal: 16 maximum: 16.2 overall_size_y: minimum: 15.8 nominal: 16 maximum: 16.2 lead_width: minimum: 0.22 nominal: 0.32 maximum: 0.38 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.65 num_pins_x: 20 num_pins_y: 20 LQFP-100_14x14mm_P0.5mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT407-1.pdf' body_size_x: minimum: 13.9 maximum: 14.1 body_size_y: minimum: 13.9 maximum: 14.1 overall_size_x: minimum: 15.75 maximum: 16.25 overall_size_y: minimum: 15.75 maximum: 16.25 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 25 num_pins_y: 25 LQFP-128_14x14mm_P0.4mm: size_source: 'https://www.renesas.com/eu/en/package-image/pdf/outdrawing/q128.14x14.pdf' body_size_x: nominal: 14 body_size_y: nominal: 14 overall_size_x: nominal: 16 overall_size_y: nominal: 16 lead_width: minimum: 0.13 nominal: 0.16 maximum: 0.23 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.4 num_pins_x: 32 num_pins_y: 32 LQFP-128_14x20mm_P0.5mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT425-1.pdf' body_size_x: minimum: 13.9 maximum: 14.1 body_size_y: minimum: 19.9 maximum: 20.1 overall_size_x: minimum: 15.85 maximum: 16.15 overall_size_y: minimum: 21.85 maximum: 22.15 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 26 num_pins_y: 38 LQFP-144_20x20mm_P0.5mm: size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=425' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 pitch: 0.5 num_pins_x: 36 num_pins_y: 36 LQFP-160_24x24mm_P0.5mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT435-1.pdf' body_size_x: minimum: 23.9 maximum: 24.1 body_size_y: minimum: 23.9 maximum: 24.1 overall_size_x: minimum: 25.85 maximum: 26.15 overall_size_y: minimum: 25.85 maximum: 26.15 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 40 num_pins_y: 40 LQFP-176_20x20mm_P0.4mm: size_source: 'https://www.onsemi.com/pub/Collateral/566DB.PDF' body_size_x: nominal: 20 tolerance: 0.1 body_size_y: nominal: 20 tolerance: 0.1 overall_size_x: nominal: 22 tolerance: 0.2 overall_size_y: nominal: 22 tolerance: 0.2 lead_width: nominal: 0.15 tolerance: [0.04, 0.05] lead_len: nominal: 0.5 tolerance: 0.2 pitch: 0.4 num_pins_x: 44 num_pins_y: 44 LQFP-176_24x24mm_P0.5mm: size_source: 'https://www.st.com/resource/en/datasheet/stm32f207vg.pdf#page=163' body_size_x: minimum: 23.9 maximum: 24.1 body_size_y: minimum: 23.9 maximum: 24.1 overall_size_x: minimum: 25.9 maximum: 26.1 overall_size_y: minimum: 25.9 maximum: 26.1 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 44 num_pins_y: 44 LQFP-208_28x28mm_P0.5mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT459-1.pdf' body_size_x: minimum: 27.9 maximum: 28.1 body_size_y: minimum: 27.9 maximum: 28.1 overall_size_x: minimum: 29.85 maximum: 30.15 overall_size_y: minimum: 29.85 maximum: 30.15 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 52 num_pins_y: 52 LQFP-216_24x24mm_P0.4mm: size_source: 'https://www.onsemi.com/pub/Collateral/561BE.PDF' body_size_x: nominal: 24 tolerance: 0 body_size_y: nominal: 24 tolerance: 0 overall_size_x: nominal: 26 tolerance: 0 overall_size_y: nominal: 26 tolerance: 0 lead_width: minimum: 0.13 maximum: 0.23 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.4 num_pins_x: 54 num_pins_y: 54 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/mqfp.yaml ================================================ FileHeader: library_Suffix: 'QFP' device_type: 'MQFP' MQFP-44_10x10mm_P0.8mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/ad7722.pdf' body_size_x: minimum: 9.8 nominal: 10 maximum: 10.2 body_size_y: minimum: 9.8 nominal: 10 maximum: 10.2 overall_size_x: minimum: 13.65 nominal: 13.9 maximum: 14.15 overall_size_y: minimum: 13.65 nominal: 13.9 maximum: 14.15 lead_width: minimum: 0.3 maximum: 0.45 lead_len: minimum: 0.73 nominal: 0.88 maximum: 1.03 pitch: 0.8 num_pins_x: 11 num_pins_y: 11 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/msop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'MSOP' MSOP-8_3x3mm_P0.65mm: size_source: 'https://www.jedec.org/system/files/docs/mo-187F.pdf variant AA' force_small_pitch_ipc_definition: True body_size_x: 3 +/-0.2 body_size_y: 3 +/-0.2 overall_size_x: 4.9 +/-0.25 lead_width: 0.22 .. 0.38 lead_len: 0.4 .. 0.6 .. 0.8 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 MSOP-8-1EP_3x3mm_P0.65mm_EP1.68x1.88mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/4440fb.pdf#page=13' force_small_pitch_ipc_definition: True body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 3 tolerance: 0.102 overall_height: maximum: 1.1 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.22 maximum: 0.38 lead_len: nominal: 0.53 tolerance: 0.152 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 1.68 tolerance: 0 EP_size_y: nominal: 1.88 tolerance: 0 # EP_mask_x: 2.46 # EP_mask_y: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.1, 1.3] # bottom_pad_size: paste_avoid_via: False MSOP-8-1EP_3x3mm_P0.65mm_EP1.73x1.85mm: size_source: 'http://www.ti.com/lit/ds/symlink/lm25085.pdf#page=32' force_small_pitch_ipc_definition: True body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 overall_height: maximum: 1.09 overall_size_x: nominal: 4.9 tolerance: 0.15 lead_width: nominal: 0.3 tolerance: [-0.05, 0.1] lead_len: nominal: 0.53 tolerance: 0.12 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 1.73 tolerance: 0.15 EP_size_y: nominal: 1.85 tolerance: 0.15 # EP_mask_x: 2.46 # EP_mask_y: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.1, 1.3] # bottom_pad_size: paste_avoid_via: False MSOP-8-1EP_3x3mm_P0.65mm_Mask1.73x2.36mm: size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/mic5355_6.pdf#page=15' force_small_pitch_ipc_definition: True body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 3.0 tolerance: 0.1 overall_height: nominal: 0.94 tolerance: 0.1 overall_size_x: nominal: 4.9 tolerance: 0 lead_width: nominal: 0.33 tolerance: [-0.1, 0.03] lead_len: nominal: 0.53 tolerance: 0.1 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 1.73 tolerance: 0 EP_size_x_overwrite: 2.5 EP_mask_x: 1.73 EP_size_y: nominal: 2.36 tolerance: 0 EP_size_y_overwrite: 3 EP_mask_y: 2.36 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1, 1] # bottom_pad_size: paste_avoid_via: False MSOP-8-1EP_3x3mm_P0.65mm_EP1.95x2.15mm: size_source: 'http://www.st.com/resource/en/datasheet/pm8834.pdf' force_small_pitch_ipc_definition: True body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 overall_height: nominal: 1.1 overall_size_x: minimum: 4.75 nominal: 4.9 maximum: 5.05 lead_width: minimum: 0.25 nominal : 0.33 maximum: 0.41 # given as 0.7 but that can not be true. (larger than pitch) lead_len: minimum: 0.4 nominal : 0.55 maximum: 0.7 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 EP_size_x: minimum: 1.63 nominal: 1.73 maximum: 1.73 EP_size_x_overwrite: 1.95 EP_size_y: minimum: 2.08 nominal: 2.18 maximum: 2.28 EP_size_y_overwrite: 2.15 # EP_mask_x: 2.46 # EP_mask_y: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.1, 1.3] # bottom_pad_size: paste_avoid_via: False ##################################################################################################### MSOP-10-1EP_3x3mm_P0.5mm_EP1.68x1.88mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/3805fg.pdf#page=18' body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 3 tolerance: 0.102 overall_height: maximum: 1.1 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.17 maximum: 0.27 lead_len: nominal: 0.53 tolerance: 0.152 pitch: 0.5 num_pins_x: 0 num_pins_y: 5 EP_size_x: nominal: 1.68 tolerance: 0 # EP_size_x_overwrite: # EP_mask_x: EP_size_y: nominal: 1.88 tolerance: 0 # EP_size_y_overwrite: # EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.1, 1.3] # bottom_pad_size: paste_avoid_via: False MSOP-10-1EP_3x3mm_P0.5mm_EP1.73x1.98mm: size_source: 'www.allegromicro.com/~/media/Files/Datasheets/A4952-3-Datasheet.ashx?la=en#page=10' body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 overall_height: # calculated using toleranced size class # (0.86 +/- 0.05) + (0.05 ... 0.15) # min_rms: 0.8892893218813452, max_rms: 1.0307106781186548 minimum: 0.89 maximum: 1.03 overall_size_x: nominal: 4.88 tolerance: 0.2 lead_width: minimum: 0.18 maximum: 0.27 lead_len: nominal: 0.53 tolerance: 0.1 pitch: 0.5 num_pins_x: 0 num_pins_y: 5 EP_size_x: nominal: 1.73 tolerance: 0 # EP_size_x_overwrite: # EP_mask_x: EP_size_y: nominal: 1.98 tolerance: 0 # EP_size_y_overwrite: # EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1, 1.2] # bottom_pad_size: paste_avoid_via: False ##################################################################################################### MSOP-12-1EP_3x4mm_P0.65mm_EP1.65x2.85mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/3652fe.pdf#page=24' force_small_pitch_ipc_definition: True body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 4 # rounded to avoid changes to the symbol datasheet: 4.039 tolerance: 0.102 overall_height: maximum: 1.1 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.22 maximum: 0.38 lead_len: nominal: 0.53 tolerance: 0.152 pitch: 0.65 num_pins_x: 0 num_pins_y: 6 EP_size_x: nominal: 1.651 tolerance: 0.102 EP_size_x_overwrite: 1.65 # avoid changes to symbol # EP_mask_x: EP_size_y: nominal: 2.845 tolerance: 0.102 EP_size_y_overwrite: 2.85 # avoid changes to symbol # EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1, 1] # bottom_pad_size: paste_avoid_via: False MSOP-12-1EP_3x4mm_P0.65mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/6957fb.pdf#page=36' force_small_pitch_ipc_definition: True body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 4 # rounded to avoid changes to the symbol datasheet: 4.039 tolerance: 0.102 overall_height: maximum: 1.1 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.22 maximum: 0.38 lead_len: nominal: 0.53 tolerance: 0.152 pitch: 0.65 num_pins_x: 0 num_pins_y: 6 ###################################################################################################### MSOP-16-1EP_3x4mm_P0.5mm_EP1.65x2.85mm: size_source: 'http://cds.linear.com/docs/en/datasheet/37551fd.pdf#page=23' body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 4 # rounded to avoid changes to the symbol datasheet: 4.039 tolerance: 0.102 overall_height: maximum: 1.1 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.17 maximum: 0.27 lead_len: nominal: 0.53 tolerance: 0.152 pitch: 0.5 num_pins_x: 0 num_pins_y: 8 EP_size_x: nominal: 1.651 tolerance: 0.102 EP_size_x_overwrite: 1.65 # avoid changes to symbol # EP_mask_x: EP_size_y: nominal: 2.845 tolerance: 0.102 EP_size_y_overwrite: 2.85 # avoid changes to symbol # EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1, 1] # bottom_pad_size: paste_avoid_via: False MSOP-16-1EP_3x4mm_P0.5mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/436412f.pdf#page=22' body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 4 # rounded to avoid changes to the symbol datasheet: 4.039 tolerance: 0.102 overall_height: maximum: 1.1 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.17 maximum: 0.27 lead_len: nominal: 0.53 tolerance: 0.152 pitch: 0.5 num_pins_x: 0 num_pins_y: 8 # By: JEFO # Email: jacob.overgaard.andersen@gmail.com MSOP-16_3x4mm_P0.5mm: size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-msop/05081669_A_MS16.pdf' body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 4.039 tolerance: 0.102 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.17 maximum: 0.27 lead_len: nominal: 0.53 tolerance: 0.152 pitch: 0.5 num_pins_x: 0 num_pins_y: 8 overall_height: maximum: 1.10 # By: JEFO # Email: jacob.overgaard.andersen@gmail.com MSOP-16-1EP_3x4mm_P0.5mm_EP1.65x2.85mm: size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-msop/05081667_F_MSE16.pdf' body_size_x: nominal: 3 tolerance: 0.102 body_size_y: nominal: 4.039 tolerance: 0.102 overall_size_x: nominal: 4.9 tolerance: 0.152 lead_width: minimum: 0.17 maximum: 0.27 lead_len: nominal: 0.53 tolerance: 0.152 overall_height: maximum: 1.10 EP_size_x: nominal: 1.651 tolerance: 0.102 EP_size_y: nominal: 2.845 tolerance: 0.102 EP_paste_coverage: 0.7 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.25 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 8 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/pqfp.yaml ================================================ FileHeader: library_Suffix: 'QFP' device_type: 'PQFP' PQFP-100_14x20mm_P0.65mm: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' force_small_pitch_ipc_definition: True body_size_x: nominal: 14 tolerance: 0 # minimum: # maximum: body_size_y: nominal: 20 tolerance: 0 overall_size_x: nominal: 17.2 tolerance: 0 overall_size_y: nominal: 23.2 tolerance: 0 lead_width: minimum: 0.22 maximum: 0.4 lead_len: minimum: 0.73 maximum: 1.03 pitch: 0.65 num_pins_x: 20 num_pins_y: 30 PQFP-144_28x28mm_P0.65mm: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' force_small_pitch_ipc_definition: True body_size_x: nominal: 28 body_size_y: nominal: 28 overall_size_x: nominal: 31.2 overall_size_y: nominal: 31.2 lead_width: minimum: 0.22 maximum: 0.4 lead_len: minimum: 0.73 maximum: 1.03 pitch: 0.65 num_pins_x: 36 num_pins_y: 36 PQFP-160_28x28mm_P0.65mm: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' force_small_pitch_ipc_definition: True body_size_x: nominal: 28 body_size_y: nominal: 28 overall_size_x: nominal: 31.2 overall_size_y: nominal: 31.2 lead_width: minimum: 0.22 maximum: 0.4 lead_len: minimum: 0.73 maximum: 1.03 pitch: 0.65 num_pins_x: 40 num_pins_y: 40 PQFP_208: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 28 body_size_y: nominal: 28 overall_size_x: nominal: 30.6 overall_size_y: nominal: 30.6 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 52 num_pins_y: 52 PQFP_240: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 32.1 body_size_y: nominal: 32.1 overall_size_x: nominal: 34.6 overall_size_y: nominal: 34.6 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 60 num_pins_y: 60 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/sc-74.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'SC-74' SC-74-6_1.50mmx2.90mm_P0.95mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT457.pdf' body_size_x: minimum: 1.3 maximum: 1.7 body_size_y: minimum: 2.7 maximum: 3.1 overall_size_x: minimum: 2.5 maximum: 3.0 overall_height: minimum: 0.9 maximum: 1.1 lead_width: minimum: 0.25 maximum: 0.40 lead_len: minimum: 0.2 maximum: 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/so.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'SO' SO-8_5.3x6.2mm_P1.27mm: size_source: 'https://www.ti.com/lit/ml/msop001a/msop001a.pdf' body_size_x: 5.00 .. 5.60 body_size_y: 5.90 .. 6.50 overall_height: 2.00 overall_size_x: 7.40 .. 8.20 lead_width: 0.35 .. 0.51 lead_len: 0.55 .. 0.95 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SO-14_3.9x8.65mm_P1.27mm: size_source: 'https://www.st.com/resource/en/datasheet/l6491.pdf' body_size_x: 3.80 .. 4.00 body_size_y: 8.55 .. 8.75 overall_height: 1.75 overall_size_x: 5.80 .. 6.20 lead_width: 0.33 .. 0.51 lead_len: 0.4 .. 1.27 pitch: 1.27 num_pins_x: 0 num_pins_y: 7 SO-14_5.3x10.2mm_P1.27mm: size_source: 'https://www.ti.com/lit/ml/msop002a/msop002a.pdf' body_size_x: 5.00 .. 5.60 body_size_y: 9.90 .. 10.50 overall_height: 2.00 overall_size_x: 7.40 .. 8.20 lead_width: 0.35 .. 0.51 lead_len: 0.55 .. 1.05 pitch: 1.27 num_pins_x: 0 num_pins_y: 7 SO-16_3.9x9.9mm_P1.27mm: size_source: 'https://www.nxp.com/docs/en/package-information/SOT109-1.pdf' body_size_x: nominal: 3.9 minimum: 3.8 maximum: 4.0 body_size_y: nominal: 9.9 minimum: 9.8 maximum: 10.0 overall_height: 1.75 overall_size_x: minimum: 5.8 maximum: 6.2 lead_width: minimum: 0.36 maximum: 0.49 lead_len: minimum: 0.4 maximum: 1.0 pitch: 1.27 num_pins_x: 0 num_pins_y: 8 SO-16_5.3x10.2mm_P1.27mm: size_source: 'https://www.ti.com/lit/ml/msop002a/msop002a.pdf' body_size_x: 5.00 .. 5.60 body_size_y: 9.90 .. 10.50 overall_height: 2.00 overall_size_x: 7.40 .. 8.20 lead_width: 0.35 .. 0.51 lead_len: 0.55 .. 1.05 pitch: 1.27 num_pins_x: 0 num_pins_y: 8 SO-20_5.3x12.6mm_P1.27mm: size_source: 'https://www.ti.com/lit/ml/msop002a/msop002a.pdf' body_size_x: 5.00 .. 5.60 body_size_y: 12.30 .. 12.90 overall_height: 2.00 overall_size_x: 7.40 .. 8.20 lead_width: 0.35 .. 0.51 lead_len: 0.55 .. 1.05 pitch: 1.27 num_pins_x: 0 num_pins_y: 10 SO-24_5.3x15mm_P1.27mm: size_source: 'https://www.ti.com/lit/ml/msop002a/msop002a.pdf' body_size_x: 5.00 .. 5.60 body_size_y: 14.70 .. 15.30 overall_height: 2.00 overall_size_x: 7.40 .. 8.20 lead_width: 0.35 .. 0.51 lead_len: 0.55 .. 1.05 pitch: 1.27 num_pins_x: 0 num_pins_y: 12 SO-8_4.0x5.0mm_P1.27mm: size_source: 'https://www.nxp.com/docs/en/data-sheet/PCF8523.pdf' body_size_x: minimum: 3.8 maximum: 4.0 # alternatively one can also specify the tolerance instead of minimum and maximum values. # If minimum and maximum values are given then the nominal value is optional. # It should only be included if it is given in the datasheet. # (If it is in the datasheet then it must be included.) body_size_y: minimum: 4.8 maximum: 5.0 overall_size_x: minimum: 5.8 maximum: 6.2 lead_width: minimum: 0.36 maximum: 0.49 lead_len: minimum: 0.4 maximum: 1.0 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SO-4_4.4x3.9mm_P2.54mm: size_source: 'https://toshiba.semicon-storage.com/info/docget.jsp?did=10047&prodName=TLP3123' body_size_x: nominal: 4.4 tolerance: 0.25 body_size_y: nominal: 3.9 tolerance: 0.25 overall_size_x: nominal: 7.0 tolerance: 0.4 lead_width: nominal: 0.4 tolerance: 0.1 lead_len: nominal: 0.6 tolerance: 0.3 pitch: 2.54 num_pins_x: 0 num_pins_y: 2 Texas_PowerPAD_SO-20-1EP_7.52x12.83mm_P1.27mm: size_source: 'http://www.ti.com/lit/ds/symlink/opa569.pdf, http://www.ti.com/lit/an/slma004b/slma004b.pdf' #custom_name_format: Texas_PowerPAD_SO-{pincount:d}-1EP_{size_x:.2g}x{size_y:.2g}mm_P{pitch:.2g}mm body_size_x: minimum: 7.45 maximum: 7.59 body_size_y: minimum: 12.7 maximum: 12.95 overall_size_x: minimum: 10.16 maximum: 10.65 overall_height: nominal: 2.65 tolerance: 0 lead_width: minimum: 0.35 maximum: 0.51 lead_len: minimum: 0.4 maximum: 1.27 pitch: 1.27 num_pins_x: 0 num_pins_y: 10 # EP_size from OPA569 datasheet # _overwrite from PowerPad app note slma004b.pdf # mask size from OPA569 datasheet Figure 16: 3.56 mm x 4.47 mm # Thermal vias from OPA569 datasheet Figure 16: 3x8=24pcs 13mil EP_size_x: minimum: 2.72 maximum: 3.81 EP_size_x_overwrite: 6.045 # 0.238" EP_mask_x: 3.56 EP_size_y: minimum: 3.49 maximum: 4.32 EP_size_y_overwrite: 12.09 # 0.476" EP_mask_y: 4.47 thermal_vias: count: [3, 8] # x-pitch 0.026" = 0.66 mm # y-pitch 0.039"/2 = 0.495 mm drill: 0.33 # 0.013" min_annular_ring: 0.08 # (0.495 spacing - 0.33 drill)/2 = 0.08 mm max ring paste_via_clearance: 0.1 EP_paste_coverage: 0.75 grid: [0.66, 0.495] paste_avoid_via: False EP_num_paste_pads: [2, 2] ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/soic.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'SOIC' SOIC-4_4.55x3.7mm_P2.54mm: custom_name_format: 'SOIC-4_4.55x3.7mm_P2.54mm' #does not take into account the excluded pins size_source: 'https://toshiba.semicon-storage.com/info/docget.jsp?did=11791&prodName=TLP185' body_size_x: minimum: 4.4 nominal: 4.55 maximum: 4.8 body_size_y: minimum: 3.45 nominal: 3.7 maximum: 3.95 overall_size_x: minimum: 6.6 nominal: 7.0 maximum: 7.4 lead_width: nominal: 0.4 lead_len: nominal: 0.5 pitch: 1.27 num_pins_x: 0 num_pins_y: 3 hidden_pins: [2, 5] SOIC-4_4.55x2.6mm_P1.27mm: size_source: 'https://toshiba.semicon-storage.com/info/docget.jsp?did=12884&prodName=TLP291' body_size_x: minimum: 4.4 nominal: 4.55 maximum: 4.8 body_size_y: minimum: 2.45 nominal: 2.6 maximum: 2.85 overall_size_x: minimum: 6.6 nominal: 7.0 maximum: 7.4 lead_width: minimum: 0.37 maximum: 0.39 lead_len: nominal: 0.5 pitch: 1.27 num_pins_x: 0 num_pins_y: 2 SOIC-8_3.9x4.9mm_P1.27mm: size_source: 'JEDEC MS-012AA, https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/soic_narrow-r/r_8.pdf' body_size_x: # from JEDEC nominal: 3.9 tolerance: 0.1 body_size_y: minimum: 4.8 maximum: 5.0 overall_height: minimum: 1.35 maximum: 1.75 overall_size_x: # from JEDEC (agrees with linked datasheet) nominal: 6 tolerance: 0.2 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SOIC-8-1EP_3.9x4.9mm_P1.27mm_EP2.29x3.0mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/ada4898-1_4898-2.pdf#page=29' body_size_x: minimum: 3.8 nominal: 3.9 maximum: 4.0 body_size_y: minimum: 4.8 nominal: 4.9 maximum: 5.0 overall_height: minimum: 1.25 maximum: 1.65 overall_size_x: minimum: 5.8 nominal: 6.0 maximum: 6.2 lead_len: minimum: 0.4 maximum: 1.27 lead_width: minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 2.29 tolerance: 0 # no tolerance given #EP_size_x_overwrite: #EP_mask_x: EP_size_y: nominal: 3.0 # 2.29+2*0.356 = 3.002 rounded to 3.0 tolerance: 0 # no tolerance given #EP_size_y_overwrite: #EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.3, 1] # bottom_pad_size: paste_avoid_via: False SOIC-8-1EP_3.9x4.9mm_P1.27mm_EP2.41x3.81mm: size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/ada4898-1_4898-2.pdf#page=29' body_size_x: minimum: 3.8 nominal: 3.9 maximum: 4.0 body_size_y: minimum: 4.8 nominal: 4.9 maximum: 5.0 overall_height: minimum: 1.25 maximum: 1.65 overall_size_x: minimum: 5.8 nominal: 6.0 maximum: 6.2 lead_len: minimum: 0.4 maximum: 1.27 lead_width: minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 2.41 tolerance: 0 # no tolerance given # EP_size_x_overwrite: 2.41 #EP_mask_x: EP_size_y: nominal: 3.81 # 3.098+2*0.356 tolerance: 0 # no tolerance given # EP_size_y_overwrite: 3.1 #EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.4, 1.4] # bottom_pad_size: paste_avoid_via: False SOIC-8-1EP_3.9x4.9mm_P1.27mm_EP2.41x3.1mm: size_source: 'http://www.ti.com/lit/ds/symlink/lm5017.pdf#page=31' body_size_x: minimum: 3.8 maximum: 4.0 body_size_y: minimum: 4.8 maximum: 5.0 overall_height: maximum: 1.7 overall_size_x: minimum: 5.8 maximum: 6.2 lead_len: minimum: 0.4 maximum: 1.27 lead_width: minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: minimum: 2.11 maximum: 2.71 EP_size_x_overwrite: 2.95 EP_mask_x: 2.71 EP_size_y: minimum: 2.8 maximum: 3.4 EP_size_y_overwrite: 4.9 EP_mask_y: 3.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.3, 1.3] # bottom_pad_size: paste_avoid_via: False SOIC-8-1EP_3.9x4.9mm_P1.27mm_EP2.41x3.3mm: size_source: 'http://www.allegromicro.com/~/media/Files/Datasheets/A4950-Datasheet.ashx#page=8' body_size_x: nominal: 3.9 tolerance: 0.1 body_size_y: nominal: 4.9 tolerance: 0.1 overall_height: maximum: 1.7 overall_size_x: nominal: 6.0 tolerance: 0.2 lead_len: minimum: 0.4 maximum: 1.27 lead_width: minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 2.41 tolerance: 0 # no tolerance given # EP_size_x_overwrite: 2.41 #EP_mask_x: EP_size_y: nominal: 3.3 tolerance: 0 # no tolerance given # EP_size_y_overwrite: 3.1 #EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.4, 1.2] # bottom_pad_size: paste_avoid_via: False SOIC-8-1EP_3.9x4.9mm_P1.27mm_EP2.514x3.2mm: size_source: 'https://www.renesas.com/eu/en/www/doc/datasheet/hip2100.pdf#page=13' body_size_x: minimum: 3.8 # rounded from 3.811 maximum: 4.0 # rounded from 3.99 body_size_y: minimum: 4.8 maximum: 5.0 # rounded from 4.98 overall_height: minimum: 1.43 maximum: 1.68 overall_size_x: minimum: 5.84 maximum: 6.2 lead_len: minimum: 0.41 maximum: 0.89 lead_width: minimum: 0.35 maximum: 0.49 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 2.514 # only maximum given but that is not supported by the script tolerance: 0 # EP_size_x_overwrite: #EP_mask_x: EP_size_y: nominal: 3.2 # only maximum given but that is not supported by the script tolerance: 0 # EP_size_y_overwrite: #EP_mask_y: # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.4, 1.0] # bottom_pad_size: paste_avoid_via: False SOIC-8-1EP_3.9x4.9mm_P1.27mm_EP2.62x3.51mm: size_source: 'https://www.monolithicpower.com/en/documentview/productdocument/index/version/2/document_type/Datasheet/lang/en/sku/MP2303A/document_id/494#page=14' body_size_x: minimum: 3.8 maximum: 4.0 body_size_y: minimum: 4.8 maximum: 5.0 overall_height: minimum: 1.3 maximum: 1.7 overall_size_x: minimum: 5.8 maximum: 6.2 lead_len: minimum: 0.41 maximum: 1.27 lead_width: minimum: 0.33 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: minimum: 2.26 maximum: 2.56 EP_size_y: minimum: 3.15 maximum: 3.45 EP_size_x_overwrite: 2.62 EP_size_y_overwrite: 3.51 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.4, 1.0] # bottom_pad_size: paste_avoid_via: False SOIC-8_5.23x5.23mm_P1.27mm: size_source: 'http://www.winbond.com/resource-files/w25q32jv%20revg%2003272018%20plus.pdf#page=68' body_size_x: minimum: 5.13 nominal: 5.23 maximum: 5.33 body_size_y: minimum: 5.13 nominal: 5.23 maximum: 5.33 overall_height: minimum: 1.75 nominal: 1.95 maximum: 2.16 overall_size_x: minimum: 7.7 nominal: 7.9 maximum: 8.1 lead_len: minimum: 0.5 nominal: 0.65 maximum: 0.8 lead_width: minimum: 0.35 nominal: 0.42 maximum: 0.48 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SOIC-8_5.275x5.275mm_P1.27mm: size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/20005045C.pdf#page=23' body_size_x: minimum: 5.15 maximum: 5.4 body_size_y: minimum: 5.15 maximum: 5.4 overall_size_x: minimum: 7.7 maximum: 8.1 overall_height: minimum: 1.75 maximum: 2.16 lead_width: minimum: 0.35 maximum: 0.5 lead_len: minimum: 0.5 maximum: 0.8 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SOIC-8_7.5x5.85mm_P1.27mm: size_source: 'http://www.ti.com/lit/ml/mpds382b/mpds382b.pdf' body_size_x: minimum: 7.4 maximum: 7.6 body_size_y: minimum: 5.75 maximum: 5.95 overall_height: maximum: 2.8 overall_size_x: nominal: 11.5 tolerance: 0.25 lead_len: minimum: 0.5 maximum: 1.0 lead_width: minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SOIC-14_3.9x8.7mm_P1.27mm: #round to two significant digits to comply with old name custom_name_format: SOIC-{pincount:d}_{size_x:.2g}x{size_y:.2g}mm_P{pitch:g}mm size_source: 'JEDEC MS-012AB, https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/soic_narrow-r/r_14.pdf' body_size_x: # from JEDEC nominal: 3.9 tolerance: 0.1 body_size_y: minimum: 8.55 maximum: 8.75 overall_height: maximum: 1.75 overall_size_x: # from JEDEC (agrees with linked datasheet) nominal: 6 tolerance: 0.2 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 7 SOIC-14W_7.5x9.0mm_P1.27mm: custom_name_format: SOIC-{pincount:d}W_{size_x:g}x{size_y:g}mm_P{pitch:g}mm size_source: 'JEDEC MS-013AF, https://www.analog.com/media/en/package-pcb-resources/package/54614177245586rw_14.pdf' body_size_x: # from JEDEC (agrees with linked datasheet) nominal: 7.5 tolerance: 0.1 body_size_y: minimum: 8.8 maximum: 9.2 overall_height: minimum: 2.35 maximum: 2.65 overall_size_x: # from JEDEC nominal: 10.3 tolerance: 0.33 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 7 SOIC-16_3.9x9.9mm_P1.27mm: size_source: 'JEDEC MS-012AC, https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/soic_narrow-r/r_16.pdf' body_size_x: # from JEDEC nominal: 3.9 tolerance: 0.1 body_size_y: minimum: 9.8 maximum: 10 overall_height: maximum: 1.75 overall_size_x: # from JEDEC (agrees with linked datasheet) nominal: 6 tolerance: 0.2 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 8 SOIC-16_4.55x10.3mm_P1.27mm: size_source: 'https://toshiba.semicon-storage.com/info/docget.jsp?did=12858&prodName=TLP291-4' body_size_x: minimum: 4.4 nominal: 4.55 maximum: 4.8 body_size_y: minimum: 10.15 nominal: 10.3 maximum: 10.55 overall_size_x: minimum: 6.6 nominal: 7.0 maximum: 7.4 lead_width: minimum: 0.39 maximum: 0.41 lead_len: nominal: 0.5 pitch: 1.27 num_pins_x: 0 num_pins_y: 8 SOIC-16W_7.5x10.3mm_P1.27mm: custom_name_format: SOIC-{pincount:d}W_{size_x:g}x{size_y:g}mm_P{pitch:g}mm size_source: 'JEDEC MS-013AA, https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/soic_wide-rw/rw_16.pdf' body_size_x: # from JEDEC (agrees with linked datasheet) nominal: 7.5 tolerance: 0.1 body_size_y: minimum: 10.1 maximum: 10.5 overall_height: minimum: 2.35 maximum: 2.65 overall_size_x: # from JEDEC nominal: 10.3 tolerance: 0.33 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 8 SOIC-16W_7.5x12.8mm_P1.27mm: #round to two significant digits to comply with old name custom_name_format: SOIC-{pincount:d}W_{size_x:.2g}x{size_y:.3g}mm_P{pitch:g}mm size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ri_soic_ic/ri_16_1.pdf' body_size_x: minimum: 7.4 maximum: 7.6 body_size_y: minimum: 12.6 maximum: 13 overall_height: minimum: 2.35 maximum: 2.65 overall_size_x: # from JEDEC nominal: 10.3 tolerance: 0.33 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 8 SOIC-18W_7.5x11.6mm_P1.27mm: #round to two significant digits to comply with old name custom_name_format: SOIC-{pincount:d}W_{size_x:.2g}x{size_y:.3g}mm_P{pitch:g}mm size_source: 'JEDEC MS-013AB, https://www.analog.com/media/en/package-pcb-resources/package/33254132129439rw_18.pdf' body_size_x: # from JEDEC (agrees with linked datasheet) nominal: 7.5 tolerance: 0.1 body_size_y: minimum: 11.35 maximum: 11.75 overall_height: minimum: 2.35 maximum: 2.65 overall_size_x: # from JEDEC nominal: 10.3 tolerance: 0.33 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 9 SOIC-20W_7.5x12.8mm_P1.27mm: #round to two significant digits to comply with old name custom_name_format: SOIC-{pincount:d}W_{size_x:.2g}x{size_y:.3g}mm_P{pitch:g}mm size_source: 'JEDEC MS-013AC, https://www.analog.com/media/en/package-pcb-resources/package/233848rw_20.pdf' body_size_x: # from JEDEC (agrees with linked datasheet) nominal: 7.5 tolerance: 0.1 body_size_y: minimum: 12.6 maximum: 13.0 overall_height: minimum: 2.35 maximum: 2.65 overall_size_x: # from JEDEC nominal: 10.3 tolerance: 0.33 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 10 SOIC-24W_7.5x15.4mm_P1.27mm: #round to two significant digits to comply with old name custom_name_format: SOIC-{pincount:d}W_{size_x:.2g}x{size_y:.3g}mm_P{pitch:g}mm size_source: 'JEDEC MS-013AD, https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/soic_wide-rw/RW_24.pdf' body_size_x: # from JEDEC (agrees with linked datasheet) nominal: 7.5 tolerance: 0.1 body_size_y: minimum: 15.2 maximum: 15.6 overall_height: minimum: 2.35 maximum: 2.65 overall_size_x: # from JEDEC nominal: 10.3 tolerance: 0.33 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 12 SOIC-28W_7.5x17.9mm_P1.27mm: #round to two significant digits to comply with old name custom_name_format: SOIC-{pincount:d}W_{size_x:.2g}x{size_y:.3g}mm_P{pitch:g}mm size_source: 'JEDEC MS-013AE, https://www.analog.com/media/en/package-pcb-resources/package/35833120341221rw_28.pdf' body_size_x: # from JEDEC (agrees with linked datasheet) nominal: 7.5 tolerance: 0.1 body_size_y: minimum: 17.7 maximum: 18.1 overall_height: minimum: 2.35 maximum: 2.65 overall_size_x: # from JEDEC nominal: 10.3 tolerance: 0.33 lead_len: minimum: 0.4 maximum: 1.27 lead_width: # from JEDEC (agrees with linked datasheet) minimum: 0.31 maximum: 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 14 SOIC-28W_7.5x18.7mm_P1.27mm: #round to two significant digits to comply with old name custom_name_format: SOIC-{pincount:d}W_{size_x:.2g}x{size_y:.3g}mm_P{pitch:g}mm size_source: 'https://www.akm.com/akm/en/file/datasheet/AK5394AVS.pdf#page=23' body_size_x: nominal: 7.5 tolerance: 0.2 body_size_y: nominal: 18.7 tolerance: 0.3 overall_height: nominal: 2.2 tolerance: 0.1 overall_size_x: nominal: 10.4 tolerance: 0.3 lead_len: nominal: 0.75 tolerance: 0.2 lead_width: nominal: 0.4 tolerance: 0.1 pitch: 1.27 num_pins_x: 0 num_pins_y: 14 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/soj.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'SOJ' SOJ-36_23.49x10.16mm_P1.27mm: size_source: 'http://www.issi.com/WW/pdf/61-64C5128AL.pdf' body_size_x: minimum: 10.03 maximum: 10.29 body_size_y: minimum: 23.36 maximum: 23.62 overall_size_x: minimum: 10.31 maximum: 10.33 lead_width: minimum: 0.38 maximum: 0.51 lead_len: minimum: 0.825 maximum: 0.95 pitch: 1.27 num_pins_x: 0 num_pins_y: 18 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/sop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'SOP' SOP-8-1EP_4.57x4.57mm_P1.27mm_EP4.57x4.45mm: size_source: 'https://ww2.minicircuits.com/case_style/XX112.pdf' body_size_x: nominal: 4.57 tolerance: 0.254 body_size_y: nominal: 4.57 tolerance: 0.254 overall_size_x: nominal: 10.16 tolerance: 0.254 lead_width: nominal: 0.38 tolerance: 0.254 lead_len: nominal: 1.78 tolerance: 0.254 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 EP_size_x: nominal: 4.57 tolerance: 0.254 EP_size_y: # not directly given in datasheet. EP edge coincides with pads. (3*1.27+0.64 = 4.45) nominal: 4.45 tolerance: 0.254 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 3] drill: 0.51 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.70 grid: [2.54, 1.27] # bottom_pad_size: paste_avoid_via: False SOP-4_3.8x4.1mm_P2.54mm: size_source: 'http://www.ixysic.com/home/pdfs.nsf/www/CPC1017N.pdf/$file/CPC1017N.pdf' body_size_x: nominal: 3.8 #rounded to avoid changing the symbol (given as 3.81) tolerance: 0.025 body_size_y: nominal: 4.1 #rounded to avoid changing the symbol (givne as 4.089) tolerance: 0.025 overall_height: # calculated from (2.03 +/-0.025) + (0.64 +/-0.04) nominal: 2.094 tolerance: 0.047 overall_size_x: nominal: 6.096 tolerance: 0.102 lead_width: nominal: 0.381 tolerance: 0 # not given lead_len: nominal: 0.559 tolerance: 0.127 pitch: 2.54 num_pins_x: 0 num_pins_y: 2 SOP-4_4.4x2.6mm_P1.27mm: size_source: 'http://www.vishay.com/docs/83510/tcmt1100.pdf' body_size_x: nominal: 4.4 tolerance: 0 # only typical size given body_size_y: nominal: 2.6 tolerance: 0.2 overall_height: # calculated from (2.0 +/-0.1) + (0.1 +/-0.1) nominal: 2.1 tolerance: 0.14 overall_size_x: nominal: 7 tolerance: 0.3 lead_width: nominal: 0.4 tolerance: 0.1 lead_len: nominal: 0.6 tolerance: [-0.3, 0.2] pitch: 1.27 num_pins_x: 0 num_pins_y: 2 SOP-8_3.76x4.96mm_P1.27mm: size_source: 'https://ww2.minicircuits.com/case_style/XX211.pdf' body_size_x: nominal: 3.76 # max (4.14) - tolerance, rounded to 2 digits (+10um) tolerance: 0.381 body_size_y: nominal: 4.96 # max (5.33) - tolerance, rounded to 2 digits (+10um) tolerance: 0.381 overall_height: maximum: 1.96 overall_size_x: minimum: 5.59 maximum: 6.35 lead_width: nominal: 0.43 tolerance: 0.127 lead_len: nominal: 0.76 tolerance: 0.381 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SOP-8_3.9x4.9mm_P1.27mm: size_source: 'http://www.macronix.com/Lists/Datasheet/Attachments/7534/MX25R3235F,%20Wide%20Range,%2032Mb,%20v1.6.pdf#page=79' body_size_x: minimum: 3.80 maximum: 4.00 body_size_y: minimum: 4.77 maximum: 5.03 overall_height: minimum: 1.45 # not specified, min.A1(0.10) + min.A2(1.35) gives this value maximum: 1.75 overall_size_x: minimum: 5.80 maximum: 6.20 lead_width: minimum: 0.36 maximum: 0.51 lead_len: minimum: 0.46 maximum: 0.86 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SOP-8_5.28x5.23mm_P1.27mm: size_source: 'http://www.macronix.com/Lists/Datasheet/Attachments/7534/MX25R3235F,%20Wide%20Range,%2032Mb,%20v1.6.pdf#page=80' body_size_x: minimum: 5.18 maximum: 5.38 body_size_y: minimum: 5.13 maximum: 5.33 overall_height: minimum: 1.75 maximum: 2.16 overall_size_x: minimum: 7.70 maximum: 8.10 lead_width: minimum: 0.36 maximum: 0.51 lead_len: minimum: 0.50 maximum: 0.80 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SOP-8_6.62x9.15mm_P2.54mm: size_source: 'http://www.ti.com/lit/ds/symlink/iso1050.pdf' body_size_x: minimum: 6.37 maximum: 6.87 body_size_y: minimum: 8.75 maximum: 9.55 overall_height: maximum: 4.85 overall_size_x: minimum: 10.1 maximum: 10.7 lead_width: minimum: 0.355 maximum: 0.555 lead_len: minimum: 1.15 maximum: 1.45 pitch: 2.54 num_pins_x: 0 num_pins_y: 4 SOP-16_4.4.55x10.3mm_P1.27mm: size_source: 'https://toshiba.semicon-storage.com/info/docget.jsp?did=12855&prodName=TLP290-4' body_size_x: nominal: 4.55 tolerance: [-0.15, 0.25] body_size_y: nominal: 10.3 tolerance: [-0.15, 0.25] overall_height: nominal: 2.1 tolerance: 0.14 overall_size_x: nominal: 7 tolerance: 0.4 lead_width: nominal: 0.4 tolerance: 0.1 lead_len: minimum: 0.5 maximum: 0.5 # Only minimum given in the datasheet. # With 0 tolerance we already get longer pads than suggested by the datasheet -> should be ok pitch: 1.27 num_pins_x: 0 num_pins_y: 8 SOP-18_7.0x12.5mm_P1.27mm: size_source: 'https://toshiba.semicon-storage.com/info/docget.jsp?did=30523' body_size_x: nominal: 7 tolerance: 0.2 body_size_y: nominal: 12.5 tolerance: 0.2 overall_height: maximum: 2.45 overall_size_x: nominal: 10.3 tolerance: 0.3 lead_width: nominal: 0.4 tolerance: 0.1 lead_len: nominal: 0.7 tolerance: 0.2 pitch: 1.27 num_pins_x: 0 num_pins_y: 9 STC_SOP-16_3.9x9.9mm_P1.27mm: size_source: 'https://www.stcmicro.com/datasheet/STC15F2K60S2-en.pdf#page=156' manufacturer: 'STC' body_size_x: # E1 minimum: 3.80 nominal: 3.90 maximum: 4.00 body_size_y: # D minimum: 9.80 nominal: 9.90 maximum: 10.00 overall_height: # A minimum: 1.35 nominal: 1.60 maximum: 1.75 overall_size_x: # E minimum: 5.80 nominal: 6.00 maximum: 6.20 lead_len: # L minimum: 0.45 nominal: 0.60 maximum: 0.80 lead_width: # b minimum: 0.35 nominal: 0.40 maximum: 0.45 pitch: 1.27 # e num_pins_x: 0 num_pins_y: 8 SOP-16_3.9x9.9mm_P1.27mm: size_source: 'https://www.diodes.com/assets/Datasheets/PAM8403.pdf' body_size_x: # E1 minimum: 3.80 maximum: 4.00 body_size_y: # D minimum: 9.80 maximum: 10.00 overall_height: # A minimum: 1.35 maximum: 1.75 overall_size_x: # E minimum: 5.80 maximum: 6.30 lead_len: # L minimum: 0.40 maximum: 1.27 lead_width: # b minimum: 0.33 maximum: 0.51 pitch: 1.27 # e num_pins_x: 0 num_pins_y: 8 SOP-20_7.5x12.8mm_P1.27mm: size_source: 'https://www.holtek.com/documents/10179/116723/sop20-300.pdf' body_size_x: nominal: 7.50 body_size_y: nominal: 12.80 overall_height: maximum: 2.65 overall_size_x: nominal: 10.30 lead_width: minimum: 0.31 maximum: 0.51 lead_len: minimum: 0.40 maximum: 1.27 pitch: 1.27 num_pins_x: 0 num_pins_y: 10 SOP-24_7.5x15.4mm_P1.27mm: size_source: 'http://www.issi.com/WW/pdf/31FL3218.pdf#page=14' body_size_x: minimum: 7.4 nominal: 7.5 maximum: 7.6 body_size_y: minimum: 15.2 nominal: 15.4 maximum: 15.6 overall_height: maximum: 2.65 overall_size_x: minimum: 10.1 nominal: 10.3 maximum: 10.61 lead_width: minimum: 0.27 maximum: 0.48 lead_len: minimum: 0.4 maximum: 1.27 pitch: 1.27 num_pins_x: 0 num_pins_y: 12 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/sot.yaml ================================================ FileHeader: library_Suffix: 'TO_SOT_SMD' device_type: 'SOT' SOT-23-5: size_source: 'https://www.jedec.org/sites/default/files/docs/Mo-178c.PDF variant AA' custom_name_format: 'SOT-23-5' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 deleted_pins: [5] SOT-23-6: size_source: 'https://www.jedec.org/sites/default/files/docs/Mo-178c.PDF variant AB' custom_name_format: 'SOT-23-6' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 SOT-23-8: size_source: 'https://www.jedec.org/sites/default/files/docs/Mo-178c.PDF variant BA' custom_name_format: 'SOT-23-8' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.22 .. 0.38 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/sso.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'SSO' SSO-8-N7_9.78x6.4mm_P2.54mm: size_source: 'https://b2b-api.panasonic.eu/file_stream/pids/fileversion/2787' body_size_y: nominal: 9.78 tolerance: 0.1 body_size_x: nominal: 6.4 tolerance: 0.1 overall_size_x: nominal: 9.62 # 7.62 + 1 + 1 +/- 0.1 tolerance: 0.1 lead_width: nominal: 1.2 # refers to fatter part of the lead, not the 0.5 at the lead ends tolerance: 0.1 lead_len: nominal: 1 tolerance: 0.1 # refers to area that can contact pad pitch: 2.54 num_pins_y: 4 num_pins_x: 0 hidden_pins: [7] ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/ssop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'SSOP' SSOP-20_5.3x7.2mm_P0.65mm: size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/40001800C.pdf' body_size_x: minimum: 5.0 maximum: 5.6 body_size_y: minimum: 6.9 maximum: 7.5 overall_size_x: minimum: 7.4 maximum: 8.2 lead_width: minimum: 0.22 maximum: 0.38 lead_len: minimum: 0.55 maximum: 0.95 pitch: 0.65 num_pins_x: 0 num_pins_y: 10 SSOP-16_5.3x6.2mm_P0.65mm: size_source: 'https://assets.nexperia.com/documents/data-sheet/74HC_HCT165.pdf#page=14' body_size_x: minimum: 5.2 maximum: 5.4 body_size_y: minimum: 6.0 maximum: 6.4 overall_size_x: minimum: 7.6 maximum: 7.9 lead_width: minimum: 0.25 maximum: 0.38 lead_len: minimum: 0.63 maximum: 1.03 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 SSOP-8_3.9x5.05mm_P1.27mm: size_source: 'http://www.fujitsu.com/downloads/MICRO/fsa/pdf/products/memory/fram/MB85RS16-DS501-00014-6v0-E.pdf' body_size_x: minimum: 3.60 maximum: 4.20 body_size_y: minimum: 4.80 maximum: 5.30 overall_size_x: minimum: 5.80 maximum: 6.20 lead_width: minimum: 0.36 maximum: 0.52 lead_len: minimum: 0.45 maximum: 0.75 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SSOP-8_5.25x5.24mm_P1.27mm: size_source: 'http://www.fujitsu.com/ca/en/Images/MB85RS2MT-DS501-00023-1v0-E.pdf' body_size_x: minimum: 5.20 maximum: 5.30 body_size_y: minimum: 5.14 maximum: 5.34 overall_size_x: minimum: 7.70 maximum: 8.25 lead_width: minimum: 0.38 maximum: 0.48 lead_len: minimum: 0.55 maximum: 0.85 pitch: 1.27 num_pins_x: 0 num_pins_y: 4 SSOP-32_11.3x20.5mm_P1.27mm: size_source: 'http://www.issi.com/WW/pdf/61-64C5128AL.pdf' body_size_x: minimum: 11.18 maximum: 11.43 body_size_y: minimum: 20.24 maximum: 20.75 overall_size_x: minimum: 13.79 maximum: 14.45 lead_width: minimum: 0.33 maximum: 0.51 lead_len: minimum: 0.38 maximum: 1.27 pitch: 1.27 num_pins_x: 0 num_pins_y: 16 SSOP-48_5.3x12.8mm_P0.5mm: size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-ssop/05081887_A_G48.pdf' body_size_x: minimum: 5.00 maximum: 5.60 body_size_y: minimum: 12.50 maximum: 13.10 overall_size_x: minimum: 7.40 maximum: 8.20 lead_width: minimum: 0.20 maximum: 0.315 lead_len: minimum: 0.55 maximum: 0.95 pitch: 0.50 num_pins_x: 0 num_pins_y: 24 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/test_hidden_deleted_pins.yaml ================================================ # hidden and deleted pins are defined and described by IPC 7351B naming convention # http://ohm.bu.edu/~pbohn/__Engineering_Reference/pcb_layout/pcbmatrix/IPC-7x51%20&%20PCBM%20Land%20Pattern%20Naming%20Convention.pdf # hidden pins remove a pin location and pin number (for example, going from pad 1 to pad 3 with pin 2 missing from the package) # deleted pins remove a pin location but not pin number (for example, pin 2 is missing from the package but the footprint has pad 2) # deleted pins do not support custom numbering schemes https://github.com/pointhi/kicad-footprint-generator/pull/371 FileHeader: library_Suffix: 'TO_SOT_SMD' device_type: 'SOT' # test add_quad_pad_border() in quad_dual_pad_border.py LQFP-48_7x7mm_P0.5mm: size_source: '~' body_size_x: 7 body_size_y: 7 overall_size_x: 9 overall_size_y: 9 lead_width: 0.17 .. 0.27 lead_len: 0.45 .. 0.75 pitch: 0.5 num_pins_x: 12 num_pins_y: 12 # test add_quad_pad_border() in quad_dual_pad_border.py with hidden pins LQFP-48_7x7mm_P0.5mm_hidden: size_source: '~' body_size_x: 7 body_size_y: 7 overall_size_x: 9 overall_size_y: 9 lead_width: 0.17 .. 0.27 lead_len: 0.45 .. 0.75 pitch: 0.5 num_pins_x: 12 num_pins_y: 12 hidden_pins: [1,15,24,30,31,44] # test add_quad_pad_border() in quad_dual_pad_border.py with deleted pins LQFP-48_7x7mm_P0.5mm_deleted: size_source: '~' body_size_x: 7 body_size_y: 7 overall_size_x: 9 overall_size_y: 9 lead_width: 0.17 .. 0.27 lead_len: 0.45 .. 0.75 pitch: 0.5 num_pins_x: 12 num_pins_y: 12 deleted_pins: [1,15,24,30,31,44] # test add_dual_pad_border_y() in quad_dual_pad_border.py SOT-23-6: size_source: '~' custom_name_format: 'SOT-23-6' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 # test add_dual_pad_border_y() in quad_dual_pad_border.py with hidden pins # manually-made footprint merged at https://github.com/KiCad/kicad-footprints/pull/2298 SOIC-14-16_3.9x9.9mm_P1.27mm: size_source: '~' body_size_x: 3.8 .. 4.0 body_size_y: 9.8 .. 10 overall_height: maximum: 1.75 overall_size_x: 6 +/-0.2 lead_len: 0.4 .. 1.27 lead_width: 0.31 .. 0.51 pitch: 1.27 num_pins_x: 0 num_pins_y: 8 hidden_pins: [2, 13] # test add_dual_pad_border_y() in quad_dual_pad_border.py with deleted pins SOT-23-5: size_source: '~' custom_name_format: 'SOT-23-5' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 deleted_pins: 5 # test add_dual_pad_border_x() in quad_dual_pad_border.py SOT-23-6R: size_source: '~' custom_name_format: 'SOT-23-6R' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 3 num_pins_y: 0 # test add_dual_pad_border_x() in quad_dual_pad_border.py with hidden pins SOT-23-6R_hidden: size_source: '~' custom_name_format: 'SOT-23-6R_Hidden' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 3 num_pins_y: 0 hidden_pins: [5] # test add_dual_pad_border_x() in quad_dual_pad_border.py with deleted pins SOT-23-6R_deleted: size_source: '~' custom_name_format: 'SOT-23-6R_Deleted' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 3 num_pins_y: 0 deleted_pins: [5] # test footprint with removed pins on both sides SOT-23: size_source: '~' custom_name_format: 'SOT-23' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 deleted_pins: [2, 4, 6] ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/test_so.yaml ================================================ ####################################################### # # Size definitions used for testing silk screen # and courtyard creation. # FileHeader: library_Suffix: 'SO' device_type: 'HTSSOP' test_original_fp: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_original_fp" body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 4.9 maximum: 5.1 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 EP_size_x: 3.4 EP_size_y: 5 EP_mask_x: 2.46 EP_mask_y: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) test_large_ep: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_large_ep" body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 4.9 maximum: 5.1 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 EP_size_x: 3.4 EP_size_y: 6 EP_mask_x: 2.46 EP_mask_y: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) test_long_body_no_ep: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_long_body_no_ep" body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 5.9 maximum: 6.1 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 test_long_body: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_long_body" body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 5.9 maximum: 6.1 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 EP_size_x: 3.4 EP_size_y: 6 EP_mask_x: 2.46 EP_mask_y: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) test_no_ep: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_no_ep" body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 4.9 maximum: 5.1 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 test_no_ep2: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_no_ep2" body_size_x: minimum: 4.3 maximum: 4.5 body_size_y: minimum: 5.4 maximum: 5.6 overall_size_x: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 test_original_fpy: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_original_fpy" body_size_y: minimum: 4.3 maximum: 4.5 body_size_x: minimum: 4.9 maximum: 5.1 overall_size_y: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_y: 0 num_pins_x: 8 EP_size_y: 3.4 EP_size_x: 5 EP_mask_y: 2.46 EP_mask_x: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) test_large_epy: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_large_epy" body_size_y: minimum: 4.3 maximum: 4.5 body_size_x: minimum: 4.9 maximum: 5.1 overall_size_y: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_y: 0 num_pins_x: 8 EP_size_y: 3.4 EP_size_x: 6 EP_mask_y: 2.46 EP_mask_x: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) test_long_body_no_epy: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_long_body_no_epy" body_size_y: minimum: 4.3 maximum: 4.5 body_size_x: minimum: 5.9 maximum: 6.1 overall_size_y: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_y: 0 num_pins_x: 8 test_long_bodyy: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_long_bodyy" body_size_y: minimum: 4.3 maximum: 4.5 body_size_x: minimum: 5.9 maximum: 6.1 overall_size_y: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_y: 0 num_pins_x: 8 EP_size_y: 3.4 EP_size_x: 6 EP_mask_y: 2.46 EP_mask_x: 2.31 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) test_no_epy: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_no_epy" body_size_y: minimum: 4.3 maximum: 4.5 body_size_x: minimum: 4.9 maximum: 5.1 overall_size_y: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_y: 0 num_pins_x: 8 test_no_epy2: size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/LTC7810.pdf' custom_name_format: "test_no_epy2" body_size_y: minimum: 4.3 maximum: 4.5 body_size_x: minimum: 5.4 maximum: 5.6 overall_size_y: minimum: 6.2 maximum: 6.6 lead_width: minimum: 0.19 maximum: 0.30 lead_len: minimum: 0.5 maximum: 0.75 pitch: 0.65 num_pins_y: 0 num_pins_x: 8 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/tqfp.yaml ================================================ FileHeader: library_Suffix: 'QFP' device_type: 'TQFP' TQFP-48_7x7mm_P0.5mm: size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/48L_TQFP_7x7x1_0mm_PT_C04-00300d.pdf' body_size_x: 7.00 # basic body_size_y: 7.00 # basic overall_height: 1.00 .. 1.20 # min calculated from A1_min + A2_min overall_size_x: 9.00 # basic overall_size_y: 9.00 # basic lead_width: 0.17 .. 0.22 .. 0.27 lead_len: 0.45 .. 0.60 .. 0.75 pitch: 0.50 num_pins_x: 12 num_pins_y: 12 TQFP-48-1EP_7x7mm_P0.5mm_EP5.0x5.0mm: size_source: 'https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2100_datasheet_Rev1.08.pdf (page 45)' body_size_x: nominal: 7 tolerance: 0 body_size_y: nominal: 7 tolerance: 0 overall_size_x: nominal: 9 tolerance: 0 overall_size_y: nominal: 9 tolerance: 0 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 12 num_pins_y: 12 EP_size_x: minimum: 4.9 nominal: 5.0 maximum: 5.1 EP_size_y: minimum: 4.9 nominal: 5.0 maximum: 5.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 #EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: True TQFP_64: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 10 body_size_y: nominal: 10 overall_size_x: nominal: 12 overall_size_y: nominal: 12 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 16 num_pins_y: 16 TQFP_100: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 14 body_size_y: nominal: 14 overall_size_x: nominal: 16 overall_size_y: nominal: 16 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 25 num_pins_y: 25 TQFP-100-1EP_14x14mm_P0.5mm_EP5.0x5.0mm: size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/tqfp_edsv/sv_100_4.pdf' body_size_x: nominal: 14 body_size_y: nominal: 14 overall_size_x: nominal: 16 overall_size_y: nominal: 16 overall_height: minimum: 1 maximum: 1.2 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.45 nominal: 0.60 maximum: 0.75 pitch: 0.5 num_pins_x: 25 num_pins_y: 25 EP_size_x: nominal: 5.0 EP_size_y: nominal: 5.0 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) # EP_size_limit_x: 3.6 #for relatively large EP pads (increase clearance) # EP_size_limit_y: 3.6 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 #EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: True TQFP_144: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 36 num_pins_y: 36 TQFP_176: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 24 body_size_y: nominal: 24 overall_size_x: nominal: 26 overall_size_y: nominal: 26 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 44 num_pins_y: 44 TQFP_176: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 24 body_size_y: nominal: 24 overall_size_x: nominal: 26 overall_size_y: nominal: 26 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 44 num_pins_y: 44 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/tsop-i.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'TSOP-I' TSOP-I-32_11.80x8.00mm_P0.50mm: size_source: 'http://www.issi.com/WW/pdf/61-64C5128AL.pdf' body_size_x: minimum: 11.70 maximum: 11.90 body_size_y: minimum: 7.90 maximum: 8.10 overall_size_x: minimum: 13.10 maximum: 13.70 lead_width: minimum: 0.16 maximum: 0.27 lead_len: minimum: 0.30 maximum: 0.70 pitch: 0.50 num_pins_x: 0 num_pins_y: 16 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/tsop-ii.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'TSOP-II' TSOP-II-44_10.16x18.41mm_P0.80mm: size_source: 'http://www.issi.com/WW/pdf/61-64C5128AL.pdf' body_size_x: minimum: 10.03 maximum: 10.29 body_size_y: minimum: 18.28 maximum: 18.54 overall_size_x: minimum: 11.56 maximum: 11.96 lead_width: minimum: 0.30 maximum: 0.45 lead_len: minimum: 0.40 maximum: 0.69 pitch: 0.80 num_pins_x: 0 num_pins_y: 22 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/tsot.yaml ================================================ FileHeader: library_Suffix: 'TO_SOT_SMD' device_type: 'TSOT' TSOT-23-5: size_source: 'https://www.jedec.org/sites/default/files/docs/MO-193D.pdf variant AB' custom_name_format: 'TSOT-23-5' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 deleted_pins: [5] TSOT-23-6: size_source: 'https://www.jedec.org/sites/default/files/docs/MO-193D.pdf variant AA' custom_name_format: 'TSOT-23-6' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.3 .. 0.5 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.95 num_pins_x: 0 num_pins_y: 3 TSOT-23-8: size_source: 'https://www.jedec.org/sites/default/files/docs/MO-193D.pdf variant BA' custom_name_format: 'TSOT-23-8' body_size_x: 1.6 body_size_y: 2.9 overall_size_x: 2.8 lead_width: 0.22 .. 0.38 lead_len: 0.3 .. 0.45 .. 0.6 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/tssop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'TSSOP' ############################################################################## # TSSOP Variations - 0.40 PITCH # BODY WIDTH (E1) = 4.40 NOM ############################################################################## TSSOP-24_4.4x5mm_P0.4mm: size_source: 'JEDEC MO-153 Var CA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 5.0 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 12 TSSOP-32_4.4x6.5mm_P0.4mm: size_source: 'JEDEC MO-153 Var CB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 6.5 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 16 TSSOP-36_4.4x7.8mm_P0.4mm: size_source: 'JEDEC MO-153 Var CC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 7.8 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 18 TSSOP-48_4.4x9.7mm_P0.4mm: size_source: 'JEDEC MO-153 Var CD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 24 ############################################################################## # TSSOP Variations - 0.40 PITCH # BODY WIDTH (E1) = 6.10 NOM ############################################################################## TSSOP-36_6.1x7.8mm_P0.4mm: size_source: 'JEDEC MO-153 Var FA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 7.8 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 18 TSSOP-48_6.1x9.7mm_P0.4mm: size_source: 'JEDEC MO-153 Var FB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 24 TSSOP-52_6.1x11mm_P0.4mm: size_source: 'JEDEC MO-153 Var FC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 26 TSSOP-56_6.1x12.5mm_P0.4mm: size_source: 'JEDEC MO-153 Var FD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 28 TSSOP-64_6.1x14mm_P0.4mm: size_source: 'JEDEC MO-153 Var FE https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 14.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 32 TSSOP-80_6.1x17mm_P0.4mm: size_source: 'JEDEC MO-153 Var FF https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 17.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 40 ############################################################################## # TSSOP Variations - 0.40 PITCH # BODY WIDTH (E1) = 8.00 NOM ############################################################################## TSSOP-48_8x9.7mm_P0.4mm: size_source: 'JEDEC MO-153 Var JA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 24 TSSOP-52_8x11mm_P0.4mm: size_source: 'JEDEC MO-153 Var JB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 26 TSSOP-56_8x12.5mm_P0.4mm: size_source: 'JEDEC MO-153 Var JC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 28 TSSOP-60_8x12.5mm_P0.4mm: size_source: 'JEDEC MO-153 Var JC-1 https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 30 TSSOP-64_8x14mm_P0.4mm: size_source: 'JEDEC MO-153 Var JD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 14.0 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 32 TSSOP-68_8x14mm_P0.4mm: size_source: 'JEDEC MO-153 Var JD-1 https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 14.0 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.13 .. 0.23 lead_len: 0.6 +/-0.15 pitch: 0.4 num_pins_x: 0 num_pins_y: 34 ############################################################################## # TSSOP Variations - 0.50 PITCH # BODY WIDTH (E1) = 4.40 NOM ############################################################################## TSSOP-20_4.4x5mm_P0.5mm: size_source: 'JEDEC MO-153 Var BA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 5.0 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 10 TSSOP-24_4.4x6.5mm_P0.5mm: size_source: 'JEDEC MO-153 Var BB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 6.5 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 12 TSSOP-28_4.4x7.8mm_P0.5mm: size_source: 'JEDEC MO-153 Var BC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 7.8 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 14 TSSOP-30_4.4x7.8mm_P0.5mm: size_source: 'JEDEC MO-153 Var BC-1 https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 7.8 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 15 TSSOP-36_4.4x9.7mm_P0.5mm: size_source: 'JEDEC MO-153 Var BD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 18 TSSOP-38_4.4x9.7mm_P0.5mm: size_source: 'JEDEC MO-153 Var BD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 19 TSSOP-44_4.4x11mm_P0.5mm: size_source: 'JEDEC MO-153 Var BE https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 22 TSSOP-50_4.4x12.5mm_P0.5mm: size_source: 'JEDEC MO-153 Var BF https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 25 ############################################################################## # TSSOP Variations - 0.50 PITCH # BODY WIDTH (E1) = 6.10 NOM ############################################################################## TSSOP-28_6.1x7.8mm_P0.5mm: size_source: 'JEDEC MO-153 Var EA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 7.8 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 14 TSSOP-36_6.1x9.7mm_P0.5mm: size_source: 'JEDEC MO-153 Var EB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 18 TSSOP-40_6.1x11mm_P0.5mm: size_source: 'JEDEC MO-153 Var EC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 20 TSSOP-44_6.1x11mm_P0.5mm: size_source: 'JEDEC MO-153 Var EC-1 https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 22 TSSOP-48_6.1x12.5mm_P0.5mm: size_source: 'JEDEC MO-153 Var ED https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 24 TSSOP-56_6.1x14mm_P0.5mm: size_source: 'JEDEC MO-153 Var EE https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 14.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 28 TSSOP-64_6.1x17mm_P0.5mm: size_source: 'JEDEC MO-153 Var EF https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 17.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.27 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 32 ############################################################################## # TSSOP Variations - 0.50 PITCH # BODY WIDTH (E1) = 8.00 NOM ############################################################################## TSSOP-36_8x9.7mm_P0.5mm: size_source: 'JEDEC MO-153 Var HA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 18 TSSOP-40_8x11mm_P0.5mm: size_source: 'JEDEC MO-153 Var HB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 20 TSSOP-48_8x12.5mm_P0.5mm: size_source: 'JEDEC MO-153 Var HC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 24 TSSOP-56_8x14mm_P0.5mm: size_source: 'JEDEC MO-153 Var HD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 14.0 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.5 num_pins_x: 0 num_pins_y: 28 ############################################################################## # TSSOP Variations - 0.65 PITCH # BODY WIDTH (E1) = 4.40 NOM ############################################################################## TSSOP-8_4.4x3mm_P0.65mm: size_source: 'JEDEC MO-153 Var AA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 3.0 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 4 TSSOP-16_4.4x5mm_P0.65mm: size_source: 'JEDEC MO-153 Var AB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 5.0 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 TSSOP-16-1EP_4.4x5mm_P0.65mm_EP3x3mm: size_source: 'Allegro A4954 https://www.allegromicro.com/-/media/Files/Datasheets/A4954-Datasheet.ashx' body_size_x: 4.4 +/-0.1 body_size_y: 5.0 +/-0.1 overall_size_x: 6.4 +/-0.2 body_height: 1.2 lead_width: 0.19 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 8 EP_size_x: nominal: 3 EP_size_y: nominal: 3 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.3 paste_avoid_via: false EP_num_paste_pads: [2, 2] TSSOP-14_4.4x5mm_P0.65mm: size_source: 'JEDEC MO-153 Var AB-1 https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 5.0 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 7 TSSOP-20_4.4x6.5mm_P0.65mm: size_source: 'JEDEC MO-153 Var AC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 6.5 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 10 TSSOP-24_4.4x7.8mm_P0.65mm: size_source: 'JEDEC MO-153 Var AD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 7.8 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 12 TSSOP-24-1EP_4.4x7.8mm_P0.65mm_EP3.2x5mm: size_source: 'https://www.st.com/resource/en/datasheet/led1642gw.pdf#page=37' body_size_x: minimum: 4.30 nominal: 4.40 maximum: 4.50 body_size_y: minimum: 7.70 nominal: 7.80 maximum: 7.90 overall_size_x: minimum: 6.30 nominal: 6.40 maximum: 6.50 body_height: 1.20 lead_width: 0.19 .. 0.30 lead_len: minimum: 0.45 nominal: 0.60 maximum: 0.75 pitch: 0.65 num_pins_x: 0 num_pins_y: 12 EP_size_x: minimum: 3.00 nominal: 3.20 maximum: 3.40 EP_size_y: minimum: 4.80 nominal: 5.00 maximum: 5.20 EP_num_paste_pads: [2, 3] TSSOP-28_4.4x9.7mm_P0.65mm: size_source: 'JEDEC MO-153 Var AE https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 4.4 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 6.4 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 14 ############################################################################## # TSSOP Variations - 0.65 PITCH # BODY WIDTH (E1) = 6.10 NOM ############################################################################## TSSOP-24_6.1x7.8mm_P0.65mm: size_source: 'JEDEC MO-153 Var DA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 7.8 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 12 TSSOP-28_6.1x9.7mm_P0.65mm: size_source: 'JEDEC MO-153 Var DB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 14 TSSOP-30_6.1x9.7mm_P0.65mm: size_source: 'JEDEC MO-153 Var DB-1 https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 15 TSSOP-32_6.1x11mm_P0.65mm: size_source: 'JEDEC MO-153 Var DC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 16 TSSOP-36_6.1x12.5mm_P0.65mm: size_source: 'JEDEC MO-153 Var DD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 18 TSSOP-38_6.1x12.5mm_P0.65mm: size_source: 'JEDEC MO-153 Var DD-1 https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 19 TSSOP-40_6.1x14mm_P0.65mm: size_source: 'JEDEC MO-153 Var DE https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 6.1 +/-0.1 body_size_y: 14.0 +/-0.1 overall_size_x: 8.1 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 20 ############################################################################## # TSSOP Variations - 0.65 PITCH # BODY WIDTH (E1) = 8.0 NOM ############################################################################## TSSOP-28_8x9.7mm_P0.65mm: size_source: 'JEDEC MO-153 Var GA https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 9.7 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 14 TSSOP-32_8x11mm_P0.65mm: size_source: 'JEDEC MO-153 Var GB https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 11.0 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 16 TSSOP-36_8x12.5mm_P0.65mm: size_source: 'JEDEC MO-153 Var GC https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 12.5 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 18 TSSOP-40_8x14mm_P0.65mm: size_source: 'JEDEC MO-153 Var GD https://www.jedec.org/document_search?search_api_views_fulltext=MO-153' body_size_x: 8.0 +/-0.1 body_size_y: 14.0 +/-0.1 overall_size_x: 10.0 body_height: 1.2 lead_width: 0.17 .. 0.30 lead_len: 0.6 +/-0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 20 ############################################################################## # TSSOP Variations - 4.0 PITCH # BODY WIDTH (E1) = 5.0 NOM ############################################################################## TSSOP-4_4.4x5.0mm_P4.0mm: size_source: 'https://www.onsemi.com/pub/Collateral/MDB8S-D.PDF#page=4' body_size_x: 4.25 .. 4.55 body_size_y: 4.85 .. 5.15 overall_size_x: 6.3 .. 6.7 body_height: 1.75 lead_width: 0.6 .. 0.7 lead_len: 0.5 .. 0.7 pitch: 4.0 num_pins_x: 0 num_pins_y: 2 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/vqfp.yaml ================================================ FileHeader: library_Suffix: 'QFP' device_type: 'VQFP' VQFP_80: #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 14 tolerance: 0 # minimum: # maximum: body_size_y: nominal: 14 overall_size_x: nominal: 16 overall_size_y: nominal: 16 lead_width: minimum: 0.22 maximum: 0.379 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.65 num_pins_x: 20 num_pins_y: 20 #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFP_100: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 14 body_size_y: nominal: 14 overall_size_x: nominal: 16 overall_size_y: nominal: 16 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.5 num_pins_x: 25 num_pins_y: 25 VQFP_128: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 14 body_size_y: nominal: 14 overall_size_x: nominal: 16 overall_size_y: nominal: 16 lead_width: minimum: 0.13 maximum: 0.23 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.4 num_pins_x: 32 num_pins_y: 32 VQFP_176: size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' body_size_x: nominal: 20 body_size_y: nominal: 20 overall_size_x: nominal: 22 overall_size_y: nominal: 22 lead_width: minimum: 0.13 maximum: 0.23 lead_len: minimum: 0.45 maximum: 0.75 pitch: 0.4 num_pins_x: 44 num_pins_y: 44 ================================================ FILE: scripts/Packages/Package_Gullwing__QFP_SOIC_SO/size_definitions/vssop.yaml ================================================ FileHeader: library_Suffix: 'SO' device_type: 'VSSOP' VSSOP-10_3x3mm_P0.5mm: size_source: 'http://www.ti.com/lit/ds/symlink/ads1115.pdf' body_size_x: minimum: 2.90 maximum: 3.10 body_size_y: minimum: 2.90 maximum: 3.10 overall_size_y: minimum: 4.85 #Datasheet value is 4.75 and 5.05 but this generate a 4.3 pin separation maximum: 5.15 #by adding 0.1 in both pin separation is correct. lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.4 maximum: 0.7 pitch: 0.5 num_pins_y: 5 num_pins_x: 0 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/Readme.md ================================================ # IPC Footprint Generator for No Lead Packages This generator uses IPC-7351B equations and fillet definitions to derive a footprint for no-lead style packages from the dimensions of the package. (The suggested footprint is generally ignored. It is only used to define the exposed pad if necessary to fulfill thermal or EMC requirements defined in the datasheet.) Fillet size definitions can be changed by pointing to a personalized IPC parameter file. The script generates footprints in zero orientation version A (pin 1 at top left corner). Pads are generated using rounded rectangle pads as suggested in preliminary releases of IPC-7351C. Examples of supported packages include: DFN, QFN, SON, LGA. ## Running the Script The script requires python 3.4 or newer. Run it with: `python3 ipc_noLead_generator.py size_definitions/dfn.yaml` (replace `dfn.yaml` with the size definition file that contains your part.) ### Optional Script Parameters * --global_config: the config file defining how the footprint will look like. (KLC) (default=`../../tools/global_config_files/config_KLCv3.0.yaml`) * --series_config: the config file defining series parameters (footprint naming). (default=`../package_config_KLCv3.yaml`) * --density: IPC density level (L,N,M) (default=`N`) * --ipc_doc: IPC definition document (default=`../ipc_definitions.yaml`) * --force_rectangle_pads: Force the generation of rectangle pads instead of rounded rectangle * --kicad4_compatible: Create footprints compatible with version 4 (avoids round-rect and custom pads). ## Size Definition Format The size definition file contains one entry per package size definition. The top level parameter will give the internal parameter set name. It must be unique in this file and should be representative of the footprint as it will be used in error messages. (It also makes later maintenance easier if it is easy to determine which footprint was generated by which parameter set.) ``` yaml internal_package_name: # parameter list (See below) ``` ### Documentation and Naming Parameters - Size source to be added to footprint documentation field (`size_source`) {url} - Footprint library name (`library`) {string} - Footprint name generation control - Device type added as prefix. Example QFN. (`device_type`) {string} - Selection of an alternative name format. Example for LGA footprints. (`use_name_format`) {enum(`LGA`, `not LGA`)} - Manufacturer name. Will be added as a prefix if given. (`manufacturer`) {string} - Part number. Will be added as a prefix if given. (`part_number`) {string} - Suffix: A custom suffix (added after pin pitch in default naming format). Can include parameters `pad_x` and `pad_y`. - Custom naming (`custom_name_format`) {python format string} - The full default format string is `{man:s}_{mpn:s}_{pkg:s}-{pincount:d}-1EP_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{suffix2:s}{vias:s}` (The same parameters can be used in your custom format. Exposed pad parameters are not available for components without exposed pad.) _Note: Contributions intended for the official library shall not include the manufacturer or part number unless the footprint is specific to that manufacturer or part. Similarly avoid custom naming for official library contributions unless required to achieve the requested name (Example TI-specific naming)._ ### Package Dimensions ![dimension example](./documentation/dimension_system.svg) - Body size (`body_size_x`, `body_size_y`, `overall_height`) {dimension} - Lead dimensions: - Lead width (`lead_width`) {dimension} - Lead length (`lead_len`) {dimension} - Optional for specifying different length for horizontal and vertical leads (`lead_len_H`, `lead_len_V`) {dimension} - Lead pitch, currently equal for all sides (`pitch`) {float} #### Pull Back Leads By default the leads are assumed to extend to the body edge. On some packages the leads are inset within the package body and these are called "pull back" leads. A typical example are packages that are called LGA by manufacturers. These packages need to select the pull back option for the IPC class (`ipc_class: 'qfn_pull_back'`) and need to be able to specify where the lead is. ![dimension example for pull back leads](./documentation/dimension_system_pull_back.svg) - Most manufacturers give the lead pull back distance (`lead_to_edge`) {dimension} - Alternatively the center position can be given (`lead_center_pos_x` and `lead_center_pos_y`) {dimension} - Another alternative is to give the center to center dimenions for leads. (`lead_center_to_center_x` and `lead_center_to_center_y`) {dimension} - Some manufacturers give the body to inner edge dimension instead of the lead length (`body_to_inside_lead_edge`) {dimenions} ### Pad Count - Pad count (`num_pins_x`, `num_pins_y`) {int} - `num_pins_x`=0 is used for generating DFN-like packages. - `num_pins_y`=0 is used to generate DFN-like package footprints but with inverted pin numbering. (Mirrored numbering scheme. Some manufactures use this style in their datasheets. Make sure you are not looking at the bottom view before using this. Not supported for QFN and similar.) ### Exposed pad Handling: ![exposed pad example](../documentation/ep_handling.svg) - Size of package exposed pad or slug (`EP_size_x`, `EP_size_y`) {dimension} - Size of the footprint pad [optional] (`EP_size_x_overwrite`, `EP_size_y_overwrite`) {float} - Pad size is equal to nominal package pad size if not given. - Use this to create a soldermask-defined pad. - Optional the size of the mask cutout (`EP_mask_x`, `EP_mask_y`) {float} - Use to create soldermask-defined pads (in combination with `EP_size_x_overwrite`) - Paste is split into a regular grid with (`EP_num_paste_pads`) {[int (x), int (y)]} - The optional paste coverage multiplier determines how much of the exposed copper area is covered by paste. (`EP_paste_coverage`) {float (0..1), default=0.65} ### Rounding of Exposed Pad Corners IPC excludes exposed pads from the requirement for rounding its corners. By default the exposed pad does therefore not use rounded corners. Some datasheets do however suggest the use of rounded corners either specified to a specific value or they appear to be equal to the normal pads. ![rounded exposed pad example](../documentation/ep_handling_rounded.svg) - Paste corner rounding is controlled by global config parameters `paste_radius_ratio` and `paste_maximum_radius` {float} - The round radius of the exposed pad can be directly set with `EP_round_radius` {float/"pad"} - The string "pad" can be used to force the same radius for the exposed pad as for the normal pads. - Alternatively the round radius ratio and max radius can be set using (`EP_round_radius_ratio`, `EP_maximum_radius`) {float} - Both these can be set per-footprint or in the global config file. ### Thermal Vias A package with exposed pad can generate a version with thermal vias. This will be generated in addition to the normal version. ![exposed pad example](../documentation/thermal_vias.svg) ``` yaml thermal_vias: # thermal via version parameters ``` - Number of vias generated in the regular grid (`count`) {[int (x), int (y)]} - Final hole size (`drill`) {float} - Optional grid (`grid`) {[float (x), float (y)]} - Auto-generated if not given (outermost pad will touch pad edge). - Paste coverage overwrite [optional] (`EP_paste_coverage`) {float (0..1)} - Thermal via version might need higher paste coverage compared to non-via version to compensate solder lost due to wicking. - Paste generator can be set up to avoid placing paste on top of vias (`paste_avoid_via`) {bool} - Clearance between via hole and paste (`paste_via_clearance`) {float} - Can lead to math exceptions. Possible fixes: - Reduce paste coverage (make sure you still have enough paste) - Play with the via grid and number of paste pads (having an outer ring of paste pads often helps. This is only possible if there is space on the outside) - If no fix is satisfactory then select avoid vias as false and increase paste coverage to combat solder loss. - Number paste pads - Quantity of paste pads (`EP_num_paste_pads`) {[int (x), int (y)]} - Alternative available if `paste_avoid_via` is true - Number of paste pads between 4 vias (`paste_between_vias`) {[int (x), int (y)]} - Number of additional paste pad rings outside the outermost vias [optional] (`paste_rings_outside`) {[int (x), int (y)]} ## Dimension Parameter Format Dimensions in datasheets are either given with minimum and maximum value (optionally including nominal) or with the nominal value plus a tolerance. Some values of the datasheet are given as reference value without tolerance. (Tolerances in this measurement are already included in other dimensions.) The script reflects this by offering the same options. Always include the nominal dimension if the tolerance is asymmetrical as the resulting footprint will differ if it is not included. _Note: Contributions that are intended for the official KiCad library must use the same dimensioning format as the datasheet. (If min, nom and max are given then all 3 must be entered into the YAML file even if the tolerance is symmetrical. Similarly use nominal plus tolerance format if the datasheet is dimensioned this way.)_ ### String-based The parameter can be given as a string in one of the following formats (white space characters are ignored). ```yaml parameter_name: 1.2 # nominal only (reference dimension marked as such in datasheet) parameter_name: 1.1 .. 1.2 .. 1.3 # min .. nominal .. max parameter_name: 1.1 .. 1.3 # min .. max parameter_name: 1.2 +/-0.1 # nominal plus symmetrical tolerance parameter_name: 1.2 +0.1 -0.05 # nominal plus asymmetrical tolerance ``` ### Dict-based ```yaml parameter_name: # nominal only nominal: 1.2 tolerance: 0 # optional to make it clear that this is the case parameter_name: # minimum maximum and nominal minimum: 1.1 nominal: 1.2 maximum: 1.3 parameter_name: # minimum maximum minimum: 1.1 maximum: 1.3 parameter_name: # nominal with symmetrical tolerance nominal: 1.2 tolerance: 0.1 parameter_name: # nominal with asymmetrical tolerance nominal: 1.2 tolerance: [-0.05, 0.1] # order does not matter, the sign is important. ``` ### Deprecated format Support for this format will be dropped in the future. This format only supports min, nom, max dimensioning. ```yaml parameter_name_min: 1.1 parameter_name: 1.2 parameter_name_max: 1.3 ``` ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/ipc_noLead_generator.py ================================================ #!/usr/bin/env python3 import sys import os import argparse import yaml import math from math import sqrt import warnings sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from ipc_pad_size_calculators import * from quad_dual_pad_border import add_dual_or_quad_pad_border sys.path.append(os.path.join(sys.path[0], "..", "utils")) from ep_handling_utils import getEpRoundRadiusParams ipc_density = 'nominal' ipc_doc_file = '../ipc_definitions.yaml' category = 'NoLead' default_library = 'Package_DFN_QFN' DEFAULT_PASTE_COVERAGE = 0.65 DEFAULT_VIA_PASTE_CLEARANCE = 0.15 DEFAULT_MIN_ANNULAR_RING = 0.15 SILK_MIN_LEN = 0.1 DEBUG_LEVEL = 0 def roundToBase(value, base): return round(value/base) * base class NoLead(): def __init__(self, configuration): self.configuration = configuration with open(ipc_doc_file, 'r') as ipc_stream: try: self.ipc_defintions = yaml.safe_load(ipc_stream) self.configuration['min_ep_to_pad_clearance'] = 0.2 #ToDo: find a settings file that can contain these. self.configuration['paste_radius_ratio'] = 0.25 self.configuration['paste_maximum_radius'] = 0.25 if 'ipc_generic_rules' in self.ipc_defintions: self.configuration['min_ep_to_pad_clearance'] = self.ipc_defintions['ipc_generic_rules'].get('min_ep_to_pad_clearance', 0.2) except yaml.YAMLError as exc: print(exc) def calcPadDetails(self, device_dimensions, EP_size, ipc_data, ipc_round_base): # Zmax = Lmin + 2JT + √(CL^2 + F^2 + P^2) # Gmin = Smax − 2JH − √(CS^2 + F^2 + P^2) # Xmax = Wmin + 2JS + √(CW^2 + F^2 + P^2) # Some manufacturers do not list the terminal spacing (S) in their datasheet but list the terminal lenght (T) # Then one can calculate # Stol(RMS) = √(Ltol^2 + 2*^2) # Smin = Lmin - 2*Tmax # Smax(RMS) = Smin + Stol(RMS) manf_tol = { 'F': self.configuration.get('manufacturing_tolerance', 0.1), 'P': self.configuration.get('placement_tolerance', 0.05) } pull_back_0 = TolerancedSize(nominal=0) pull_back = device_dimensions.get('lead_to_edge', pull_back_0) if 'lead_center_pos_x' in device_dimensions or 'lead_center_pos_y' in device_dimensions: Gmin_x, Zmax_x, Xmax = ipc_pad_center_plus_size(ipc_data, ipc_round_base, manf_tol, center_position=device_dimensions.get('lead_center_pos_x', TolerancedSize(nominal=0)), lead_length=device_dimensions.get('lead_len_H'), lead_width=device_dimensions['lead_width']) Gmin_y, Zmax_y, Xmax_y_ignored = ipc_pad_center_plus_size(ipc_data, ipc_round_base, manf_tol, center_position=device_dimensions.get('lead_center_pos_y', TolerancedSize(nominal=0)), lead_length=device_dimensions.get('lead_len_H'), lead_width=device_dimensions['lead_width']) else: Gmin_x, Zmax_x, Xmax = ipc_body_edge_inside_pull_back( ipc_data, ipc_round_base, manf_tol, body_size=device_dimensions['body_size_x'], lead_width=device_dimensions['lead_width'], lead_len=device_dimensions.get('lead_len_H'), body_to_inside_lead_edge=device_dimensions.get('body_to_inside_lead_edge'), heel_reduction=device_dimensions.get('heel_reduction', 0), pull_back=pull_back ) Gmin_y, Zmax_y, Xmax_y_ignored = ipc_body_edge_inside_pull_back( ipc_data, ipc_round_base, manf_tol, body_size=device_dimensions['body_size_y'], lead_width=device_dimensions['lead_width'], lead_len=device_dimensions.get('lead_len_V'), body_to_inside_lead_edge=device_dimensions.get('body_to_inside_lead_edge'), heel_reduction=device_dimensions.get('heel_reduction', 0), pull_back=pull_back ) min_ep_to_pad_clearance = self.configuration['min_ep_to_pad_clearance'] heel_reduction_max = 0 if Gmin_x - 2*min_ep_to_pad_clearance < EP_size['x']: heel_reduction_max = ((EP_size['x'] + 2*min_ep_to_pad_clearance - Gmin_x)/2) #print('{}, {}, {}'.format(Gmin_x, EP_size['x'], min_ep_to_pad_clearance)) Gmin_x = EP_size['x'] + 2*min_ep_to_pad_clearance if Gmin_y - 2*min_ep_to_pad_clearance < EP_size['y']: heel_reduction = ((EP_size['y'] + 2*min_ep_to_pad_clearance - Gmin_y)/2) if heel_reduction>heel_reduction_max: heel_reduction_max = heel_reduction Gmin_y = EP_size['y'] + 2*min_ep_to_pad_clearance heel_reduction_max += device_dimensions.get('heel_reduction', 0) #include legacy stuff if heel_reduction_max > 0 and DEBUG_LEVEL >= 1: print('Heel reduced by {:.4f} to reach minimum EP to pad clearances'.format(heel_reduction_max)) Pad = {} Pad['left'] = {'center':[-(Zmax_x+Gmin_x)/4, 0], 'size':[(Zmax_x-Gmin_x)/2,Xmax]} Pad['right'] = {'center':[(Zmax_x+Gmin_x)/4, 0], 'size':[(Zmax_x-Gmin_x)/2,Xmax]} Pad['top'] = {'center':[0,-(Zmax_y+Gmin_y)/4], 'size':[Xmax,(Zmax_y-Gmin_y)/2]} Pad['bottom'] = {'center':[0,(Zmax_y+Gmin_y)/4], 'size':[Xmax,(Zmax_y-Gmin_y)/2]} return Pad @staticmethod def deviceDimensions(device_size_data, fp_id): unit = device_size_data.get('unit') dimensions = { 'body_size_x': TolerancedSize.fromYaml(device_size_data, base_name='body_size_x', unit=unit), 'body_size_y': TolerancedSize.fromYaml(device_size_data, base_name='body_size_y', unit=unit), 'lead_width': TolerancedSize.fromYaml(device_size_data, base_name='lead_width', unit=unit), 'pitch': TolerancedSize.fromYaml(device_size_data, base_name='pitch', unit=unit).nominal } dimensions['has_EP'] = False if 'EP_size_x_min' in device_size_data and 'EP_size_x_max' in device_size_data or 'EP_size_x' in device_size_data: dimensions['EP_size_x'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_size_x', unit=unit) dimensions['EP_size_y'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_size_y', unit=unit) dimensions['has_EP'] = True dimensions['EP_center_x'] = TolerancedSize(nominal=0) dimensions['EP_center_y'] = TolerancedSize(nominal=0) if 'EP_center_x' in device_size_data and 'EP_center_y' in device_size_data: dimensions['EP_center_x'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_center_x', unit=unit) dimensions['EP_center_y'] = TolerancedSize.fromYaml(device_size_data, base_name='EP_center_y', unit=unit) if 'heel_reduction' in device_size_data: print( "\033[1;35mThe use of manual heel reduction is deprecated. It is automatically calculated from the minimum EP to pad clearance (ipc config file)\033[0m" ) dimensions['heel_reduction'] = device_size_data.get('heel_reduction', 0) if 'lead_to_edge' in device_size_data: dimensions['lead_to_edge'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_to_edge', unit=unit) if 'lead_center_pos_x' in device_size_data: dimensions['lead_center_pos_x'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_center_pos_x', unit=unit) if 'lead_center_to_center_x' in device_size_data: dimensions['lead_center_pos_x'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_center_to_center_x', unit=unit)/2 if 'lead_center_pos_y' in device_size_data: dimensions['lead_center_pos_y'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_center_pos_y', unit=unit) if 'lead_center_to_center_y' in device_size_data: dimensions['lead_center_pos_y'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_center_to_center_y', unit=unit)/2 dimensions['lead_len_H'] = None dimensions['lead_len_V'] = None if 'lead_len_H' in device_size_data and 'lead_len_V' in device_size_data: dimensions['lead_len_H'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_len_H', unit=unit) dimensions['lead_len_V'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_len_V', unit=unit) elif 'lead_len' in device_size_data or ( 'lead_len_min' in device_size_data and 'lead_len_max' in device_size_data): dimensions['lead_len_H'] = TolerancedSize.fromYaml(device_size_data, base_name='lead_len', unit=unit) dimensions['lead_len_V'] = dimensions['lead_len_H'] if 'body_to_inside_lead_edge' in device_size_data: dimensions['body_to_inside_lead_edge'] = TolerancedSize.fromYaml(device_size_data, base_name='body_to_inside_lead_edge', unit=unit) elif dimensions['lead_len_H'] is None: raise KeyError('{}: Either lead lenght or inside lead to edge dimension must be given.'.format(fp_id)) return dimensions def generateFootprint(self, device_params, fp_id): print('Building footprint for parameter set: {}'.format(fp_id)) device_dimensions = NoLead.deviceDimensions(device_params, fp_id) if device_dimensions['has_EP'] and 'thermal_vias' in device_params: self.__createFootprintVariant(device_params, device_dimensions, True) self.__createFootprintVariant(device_params, device_dimensions, False) def __createFootprintVariant(self, device_params, device_dimensions, with_thermal_vias): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = device_params.get('library', default_library) pincount = device_params['num_pins_x']*2 + device_params['num_pins_y']*2 default_ipc_config = 'qfn_pull_back' if 'lead_to_edge' in device_params else 'qfn' if device_params.get('ipc_class', default_ipc_config) == 'qfn_pull_back': ipc_reference = 'ipc_spec_flat_no_lead_pull_back' else: ipc_reference = 'ipc_spec_flat_no_lead' used_density = device_params.get('ipc_density', ipc_density) ipc_data_set = self.ipc_defintions[ipc_reference][used_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] layout = '' if device_dimensions['has_EP']: name_format = self.configuration['fp_name_EP_format_string_no_trailing_zero'] if 'EP_size_x_overwrite' in device_params: EP_size = { 'x':device_params['EP_size_x_overwrite'], 'y':device_params['EP_size_y_overwrite'] } else: EP_size = { 'x':device_dimensions['EP_size_x'].nominal, 'y':device_dimensions['EP_size_y'].nominal } EP_center = { 'x':device_dimensions['EP_center_x'].nominal, 'y':device_dimensions['EP_center_y'].nominal } else: name_format = self.configuration['fp_name_format_string_no_trailing_zero'] if device_params.get('use_name_format', 'QFN') == 'LGA': name_format = self.configuration['fp_name_lga_format_string_no_trailing_zero'] if device_params['num_pins_x'] > 0 and device_params['num_pins_y'] > 0: layout = self.configuration['lga_layout_border'].format( nx=device_params['num_pins_x'], ny=device_params['num_pins_y']) EP_size = {'x':0, 'y':0} if 'custom_name_format' in device_params: name_format = device_params['custom_name_format'] pad_details = self.calcPadDetails(device_dimensions, EP_size, ipc_data_set, ipc_round_base) pad_suffix = '_Pad{pad_x:.2f}x{pad_y:.2f}mm'.format(pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) pad_suffix = '' if device_params.get('include_pad_size', 'none') not in ('fp_name_only', 'both') else pad_suffix pad_suffix_3d = '' if device_params.get('include_pad_size', 'none') not in ('both') else pad_suffix suffix = device_params.get('suffix', '') suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix','${KISYS3DMOD}') size_x = device_dimensions['body_size_x'].nominal size_y = device_dimensions['body_size_y'].nominal fp_name = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_dimensions['pitch'], layout=layout, ep_size_x = EP_size['x'], ep_size_y = EP_size['y'], suffix=pad_suffix, suffix2=suffix, vias=self.configuration.get('thermal_via_suffix', '_ThermalVias') if with_thermal_vias else '' ).replace('__','_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_dimensions['pitch'], layout=layout, ep_size_x = EP_size['x'], ep_size_y = EP_size['y'], suffix=pad_suffix_3d, suffix2=suffix_3d, vias='' ).replace('__','_').lstrip('_') if 'fp_name_prefix' in device_params: prefix = device_params['fp_name_prefix'] if not prefix.endswith('_'): prefix += '_' fp_name = prefix + fp_name fp_name_2 = prefix + fp_name_2 model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = device_params['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=device_params['device_type'], category=category ).lstrip()) kicad_mod.setAttribute('smd') pad_radius = add_dual_or_quad_pad_border(kicad_mod, self.configuration, pad_details, device_params) if device_dimensions['has_EP']: pad_shape_details = getEpRoundRadiusParams(device_params, self.configuration, pad_radius) ep_pad_number = device_params.get('EP_pin_number', pincount+1) if with_thermal_vias: thermals = device_params['thermal_vias'] paste_coverage = thermals.get('EP_paste_coverage', device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE)) kicad_mod.append(ExposedPad( number=ep_pad_number, size=EP_size, at=EP_center, paste_layout=thermals.get('EP_num_paste_pads', device_params.get('EP_num_paste_pads', 1)), paste_coverage=paste_coverage, via_layout=thermals.get('count', 0), paste_between_vias=thermals.get('paste_between_vias'), paste_rings_outside=thermals.get('paste_rings_outside'), via_drill=thermals.get('drill', 0.3), via_grid=thermals.get('grid'), paste_avoid_via=thermals.get('paste_avoid_via', True), via_paste_clarance=thermals.get('paste_via_clearance', DEFAULT_VIA_PASTE_CLEARANCE), min_annular_ring=thermals.get('min_annular_ring', DEFAULT_MIN_ANNULAR_RING), bottom_pad_min_size=thermals.get('bottom_min_size', 0), kicad4_compatible=args.kicad4_compatible, **pad_shape_details )) else: kicad_mod.append(ExposedPad( number=ep_pad_number, size=EP_size, at=EP_center, paste_layout=device_params.get('EP_num_paste_pads', 1), paste_coverage=device_params.get('EP_paste_coverage', DEFAULT_PASTE_COVERAGE), kicad4_compatible=args.kicad4_compatible, **pad_shape_details )) body_edge = { 'left': -size_x/2, 'right': size_x/2, 'top': -size_y/2, 'bottom': size_y/2 } bounding_box = body_edge.copy() if device_params['num_pins_x'] == 0 and EP_size['y'] > size_y: bounding_box['top'] = -EP_size['y']/2 bounding_box['bottom'] = EP_size['y']/2 if device_params['num_pins_y'] == 0 and EP_size['x'] > size_x: bounding_box['left'] = -EP_size['x']/2 bounding_box['right'] = EP_size['x']/2 if device_params['num_pins_y'] > 0: bounding_box['left'] = pad_details['left']['center'][0] - pad_details['left']['size'][0]/2 bounding_box['right'] = pad_details['right']['center'][0] + pad_details['right']['size'][0]/2 if device_params['num_pins_x'] > 0: bounding_box['top'] = pad_details['top']['center'][1] - pad_details['top']['size'][1]/2 bounding_box['bottom'] = pad_details['bottom']['center'][1] + pad_details['bottom']['size'][1]/2 pad_width = pad_details['top']['size'][0] for key in body_edge: if bounding_box[key] < 0: bounding_box[key] = min(bounding_box[key], body_edge[key]) else: bounding_box[key] = max(bounding_box[key], body_edge[key]) # ############################ SilkS ################################## silk_pad_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 silk_offset = configuration['silk_fab_offset'] if device_params['num_pins_x'] == 0: kicad_mod.append(Line( start={'x':0, 'y':body_edge['top']-silk_offset}, end={'x':body_edge['right'], 'y':body_edge['top']-silk_offset}, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(Line( start={'x':body_edge['left'], 'y':body_edge['bottom']+silk_offset}, end={'x':body_edge['right'], 'y':body_edge['bottom']+silk_offset}, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) elif device_params['num_pins_y'] == 0: kicad_mod.append(Line( start={'y':0, 'x':body_edge['left']-silk_offset}, end={'y':body_edge['bottom'], 'x':body_edge['left']-silk_offset}, width=configuration['silk_line_width'], layer="F.SilkS")) kicad_mod.append(Line( start={'y':body_edge['top'], 'x':body_edge['right']+silk_offset}, end={'y':body_edge['bottom'], 'x':body_edge['right']+silk_offset}, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) else: sx1 = -(device_dimensions['pitch']*(device_params['num_pins_x']-1)/2.0 + pad_width/2.0 + silk_pad_offset) sy1 = -(device_dimensions['pitch']*(device_params['num_pins_y']-1)/2.0 + pad_width/2.0 + silk_pad_offset) poly_silk = [ {'x': sx1, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': sy1} ] if sx1 - SILK_MIN_LEN < body_edge['left']-silk_offset: poly_silk = poly_silk[1:] if sy1 - SILK_MIN_LEN < body_edge['top']-silk_offset: poly_silk = poly_silk[:-1] if len(poly_silk) > 1: kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0, y_mirror=0)) if len(poly_silk) > 2: kicad_mod.append(Line( start={'x': sx1, 'y': body_edge['top']-silk_offset}, end={'x': body_edge['left']-silk_offset, 'y': body_edge['top']-silk_offset}, width=configuration['silk_line_width'], layer="F.SilkS")) # # ######################## Fabrication Layer ########################### fab_bevel_size = min(configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative']*min(size_x, size_y)) poly_fab = [ {'x': body_edge['left']+fab_bevel_size, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']+fab_bevel_size}, {'x': body_edge['left']+fab_bevel_size, 'y': body_edge['top']}, ] kicad_mod.append(PolygoneLine( polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] cy1=roundToBase(bounding_box['top']-off, grid) kicad_mod.append(RectLine( start={ 'x':roundToBase(bounding_box['left']-off, grid), 'y':cy1 }, end={ 'x':roundToBase(bounding_box['right']+off, grid), 'y':roundToBase(bounding_box['bottom']+off, grid) }, width=configuration['courtyard_line_width'], layer='F.CrtYd')) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top': cy1, 'bottom': -cy1}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('files', metavar='file', type=str, nargs='+', help='list of files holding information about what devices should be created.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../package_config_KLCv3.yaml') parser.add_argument('--density', type=str, nargs='?', help='IPC density level (L,N,M)', default='N') parser.add_argument('--ipc_doc', type=str, nargs='?', help='IPC definition document', default='../ipc_definitions.yaml') parser.add_argument('--force_rectangle_pads', action='store_true', help='Force the generation of rectangle pads instead of rounded rectangle') parser.add_argument('--kicad4_compatible', action='store_true', help='Create footprints kicad 4 compatible') parser.add_argument('-v', '--verbose', action='count', help='set debug level') args = parser.parse_args() if args.density == 'L': ipc_density = 'least' elif args.density == 'M': ipc_density = 'most' if args.verbose: DEBUG_LEVEL = args.verbose ipc_doc_file = args.ipc_doc with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) if args.force_rectangle_pads or args.kicad4_compatible: configuration['round_rect_max_radius'] = None configuration['round_rect_radius_ratio'] = 0 configuration['kicad4_compatible'] = args.kicad4_compatible for filepath in args.files: no_lead = NoLead(configuration) with open(filepath, 'r') as command_stream: try: cmd_file = yaml.safe_load(command_stream) except yaml.YAMLError as exc: print(exc) for pkg in cmd_file: no_lead.generateFootprint(cmd_file[pkg], pkg) ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/qfn.py ================================================ #!/usr/bin/env python3 import sys import os import re # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) lib_name = "Package_DFN_QFN" from KicadModTree import * def qfn(args): footprint_name = args["name"] desc = args["description"] pkgWidth = args["pkg_width"] pkgHeight = args["pkg_height"] pitch = args["pitch"] nVertPads = args["n_vert_pads"] nHorzPads = args["n_horz_pads"] padWidth = args["pad_width"] padHeight = args["pad_height"] padHDistance = args["pad_h_distance"] padVDistance = args["pad_v_distance"] cornerPads = args["corner_pads"] cornerPadSize = args["corner_pad_size"] cornerPadHDistance = args["corner_pad_h_distance"] cornerPadVDistance = args["corner_pad_v_distance"] centerPad = args["center_pad"] centerPadWidth = args["center_pad_width"] centerPadHeight = args["center_pad_height"] centerPadHDiv = args["center_pad_h_div"] centerPadVDiv = args["center_pad_v_div"] pasteMarginRatio = args["paste_margin_ratio"] thermalVias = args["thermal_vias"] viaSize = args["via_size"] pat = re.compile('_ThermalVias') model = pat.sub("", footprint_name) f = Footprint(footprint_name) f.setDescription(desc) f.setTags("QFN " + str(pitch)) f.setAttribute("smd") f.append(Model(filename="${KISYS3DMOD}/Package_DFN_QFN.3dshapes/" + model + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) d = [viaSize, viaSize] p1 = [viaSize + 0.3, viaSize + 0.3] p2 = [padWidth, padHeight] p3 = [cornerPadSize, cornerPadSize] s1 = [0.65, 0.65] s2 = [1.0, 1.0] t1 = 0.125 t2 = 0.15 wCrtYd = 0.05 wFab = 0.10 wSilkS = 0.12 padShape = Pad.SHAPE_RECT chamfer = min(1.0, 0.25*min(pkgWidth, pkgHeight)) silkOffset = 0.125 crtYd = 0.25 silkClearance = 0.2 + wSilkS / 2 bottomPadMargin = 0.5 xCenter = 0.0 xLeftFab = xCenter - pkgWidth / 2 xRightFab = xCenter + pkgWidth / 2 xChamferFab = xLeftFab + chamfer xPadLeft = xCenter - (padHDistance / 2) xPadRight = xCenter + (padHDistance / 2) xLeftCrtYd = xPadLeft - (padWidth / 2 + crtYd) xRightCrtYd = xPadRight + (padWidth / 2 + crtYd) yCenter = 0.0 yTopFab = yCenter - pkgHeight / 2 yBottomFab = yCenter + pkgHeight / 2 yChamferFab = yTopFab + chamfer yPadTop = yCenter - (padVDistance / 2) yPadBottom = yCenter + (padVDistance / 2) yTopCrtYd = yPadTop - (padWidth / 2 + crtYd) yBottomCrtYd = yPadBottom + (padWidth / 2 + crtYd) yRef = yTopCrtYd - 0.75 yValue = yBottomCrtYd + 0.75 if cornerPads: hDist = (cornerPadHDistance + cornerPadSize) / 2 + silkClearance vDist = (cornerPadVDistance + cornerPadSize) / 2 + silkClearance xLeftSilk = xCenter - hDist xRightSilk = xCenter + hDist yTopSilk = yCenter - vDist yBottomSilk = yCenter + vDist else: xLeftSilk = xLeftFab - silkOffset xRightSilk = xRightFab + silkOffset yTopSilk = yTopFab - silkOffset yBottomSilk = yBottomFab + silkOffset h2 = (pitch * (nHorzPads - 1) + padHeight) / 2 + silkClearance v2 = (pitch * (nVertPads - 1) + padHeight) / 2 + silkClearance xLeft2Silk = xCenter - h2 xRight2Silk = xCenter + h2 yTop2Silk = yCenter - v2 yBottom2Silk = yCenter + v2 # Text f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s2, thickness=t2)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s2, thickness=t2)) f.append(Text(type="user", text="%R", at=[xCenter, yCenter], layer="F.Fab", size=s1, thickness=t1)) # Fab f.append(PolygoneLine(polygone=[[xRightFab, yBottomFab], [xLeftFab, yBottomFab], [xLeftFab, yChamferFab], [xChamferFab, yTopFab], [xRightFab, yTopFab], [xRightFab, yBottomFab]], layer="F.Fab", width=wFab)) # Courtyard f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) # Silk f.append(PolygoneLine(polygone=[[xRight2Silk, yTopSilk], [xRightSilk, yTopSilk], [xRightSilk, yTop2Silk]], layer="F.SilkS", width=wSilkS)) f.append(PolygoneLine(polygone=[[xLeft2Silk, yBottomSilk], [xLeftSilk, yBottomSilk], [xLeftSilk, yBottom2Silk]], layer="F.SilkS", width=wSilkS)) f.append(PolygoneLine(polygone=[[xRight2Silk, yBottomSilk], [xRightSilk, yBottomSilk], [xRightSilk, yBottom2Silk]], layer="F.SilkS", width=wSilkS)) f.append(Line(start=[xLeftSilk, yTopSilk], end=[xLeft2Silk, yTopSilk], layer="F.SilkS", width=wSilkS)) # Pads def padStart(n): return (n-1) * pitch / 2 padNo = 1 if cornerPads: f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xCenter - cornerPadHDistance / 2, yCenter - cornerPadVDistance / 2], size=p3, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 for i in range(0, nVertPads): y = yCenter - padStart(nVertPads) + i * pitch f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=padShape, at=[xPadLeft, y], size=p2, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 if cornerPads: f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xCenter - cornerPadHDistance / 2, yCenter + cornerPadVDistance / 2], size=p3, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 for i in range(0, nHorzPads): x = xCenter - padStart(nHorzPads) + i * pitch f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=padShape, rotation=90.0, at=[x, yPadBottom], size=p2, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 if cornerPads: f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xCenter + cornerPadHDistance / 2, yCenter + cornerPadVDistance / 2], size=p3, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 for i in range(0, nVertPads): y = yCenter + padStart(nVertPads) - i * pitch f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=padShape, at=[xPadRight, y], size=p2, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 if cornerPads: f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xCenter + cornerPadHDistance / 2, yCenter - cornerPadVDistance / 2], size=p3, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 for i in range(0, nHorzPads): x = xCenter + padStart(nHorzPads) - i * pitch f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=padShape, rotation=90.0, at=[x, yPadTop], size=p2, layers=Pad.LAYERS_SMT)) padNo = padNo + 1 if centerPad: if thermalVias: f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xCenter, yCenter], size=[centerPadWidth + 2 * bottomPadMargin, centerPadHeight + 2 * bottomPadMargin], layers=["B.Cu"])) f.append(Pad(number=str(padNo), type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[xCenter, yCenter], size=[centerPadWidth, centerPadHeight], layers=["F.Cu", "F.Mask"])) subPadWidth = centerPadWidth / centerPadHDiv subPadHeight = centerPadHeight / centerPadVDiv subPadStartX = xCenter - (centerPadHDiv - 1) * subPadWidth / 2 subPadStartY = yCenter - (centerPadVDiv - 1) * subPadHeight / 2 pasteRatio = 1 + 2 * pasteMarginRatio for i in range(0, centerPadHDiv): x = subPadStartX + i * subPadWidth for j in range(0, centerPadVDiv): y = subPadStartY + j * subPadHeight f.append(Pad(number="", type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[x, y], size=[subPadWidth * pasteRatio, subPadHeight * pasteRatio], layers=["F.Paste"])) if thermalVias: nHVias = 2 * centerPadHDiv - 1 nVVias = 2 * centerPadVDiv - 1 viaHSpace = centerPadWidth / (nHVias + 1) viaVSpace = centerPadHeight / (nVVias + 1) viaStartX = xCenter - (nHVias - 1) * viaHSpace / 2 viaStartY = yCenter - (nVVias - 1) * viaVSpace / 2 for i in range(0, nHVias): x = viaStartX + i * viaHSpace for j in range(0, nVVias): y = viaStartY + j * viaVSpace if i % 2 == 1 or j % 2 == 1: f.append(Pad(number=str(padNo), type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[x, y], size=p1, layers=["*.Cu"], drill=d)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name) file_handler = KicadFileHandler(f) file_handler.writeFile(filename) if __name__ == '__main__': parser = ModArgparser(qfn) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("description", type=str, required=True) parser.add_parameter("pkg_width", type=float, required=True) parser.add_parameter("pkg_height", type=float, required=True) parser.add_parameter("pitch", type=float, required=False, default=0.5) parser.add_parameter("n_vert_pads", type=int, required=True) parser.add_parameter("n_horz_pads", type=int, required=True) parser.add_parameter("pad_width", type=float, required=False, default=0.9) parser.add_parameter("pad_height", type=float, required=False, default=0.3) parser.add_parameter("pad_h_distance", type=float, required=True) parser.add_parameter("pad_v_distance", type=float, required=True) parser.add_parameter("corner_pads", type=bool, required=False, default=False) parser.add_parameter("corner_pad_size", type=float, required=False, default=0.3) parser.add_parameter("corner_pad_h_distance", type=float, required=False, default=2.5) parser.add_parameter("corner_pad_v_distance", type=float, required=False, default=2.5) parser.add_parameter("center_pad", type=bool, required=False, default=False) parser.add_parameter("center_pad_width", type=float, required=False, default=1.8) parser.add_parameter("center_pad_height", type=float, required=False, default=1.8) parser.add_parameter("center_pad_h_div", type=int, required=False, default=2) parser.add_parameter("center_pad_v_div", type=int, required=False, default=2) parser.add_parameter("paste_margin_ratio", type=float, required=False, default=-0.2) parser.add_parameter("thermal_vias", type=bool, required=False, default=False) parser.add_parameter("via_size", type=float, required=False, default=0.3) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/qfn.yml ================================================ SiliconLabs_QFN-20-1EP_3x3mm_Pitch0.5mm_ThermalVias: description: "20-Lead Plastic Quad Flat, No Lead Package - 3x3 mm Body [QFN] with corner pads and thermal vias; see figure 8.2 of https://www.silabs.com/documents/public/data-sheets/efm8bb1-datasheet.pdf" pkg_width: 3.0 pkg_height: 3.0 pitch: 0.5 n_horz_pads: 4 n_vert_pads: 4 pad_width: 0.9 pad_height: 0.3 pad_h_distance: 3.1 pad_v_distance: 3.1 corner_pads: true corner_pad_size: 0.3 corner_pad_h_distance: 2.5 corner_pad_v_distance: 2.5 center_pad: true center_pad_width: 1.8 center_pad_height: 1.8 center_pad_h_div: 2 center_pad_v_div: 2 paste_margin_ratio: -0.2 thermal_vias: true via_size: 0.3 QFN-48-1EP_6x6mm_Pitch0.4mm_ThermalVias: description: "48-Lead Plastic Quad Flat, No Lead Package - 6x6 mm Body [QFN] with thermal vias; see figure 7.2 of https://static.dev.sifive.com/SiFive-FE310-G000-datasheet-v1.0.4.pdf" pkg_width: 6.0 pkg_height: 6.0 pitch: 0.4 n_horz_pads: 12 n_vert_pads: 12 pad_width: 0.65 pad_height: 0.2 pad_h_distance: 5.85 pad_v_distance: 5.85 corner_pads: false center_pad: true center_pad_width: 4.4 center_pad_height: 4.4 center_pad_h_div: 3 center_pad_v_div: 3 paste_margin_ratio: -0.2 thermal_vias: true via_size: 0.3 SiliconLabs_QFN-20-1EP_3x3mm_Pitch0.5mm: description: "20-Lead Plastic Quad Flat, No Lead Package - 3x3 mm Body [QFN] with corner pads; see figure 8.2 of https://www.silabs.com/documents/public/data-sheets/efm8bb1-datasheet.pdf" pkg_width: 3.0 pkg_height: 3.0 pitch: 0.5 n_horz_pads: 4 n_vert_pads: 4 pad_width: 0.9 pad_height: 0.3 pad_h_distance: 3.1 pad_v_distance: 3.1 corner_pads: true corner_pad_size: 0.3 corner_pad_h_distance: 2.5 corner_pad_v_distance: 2.5 center_pad: true center_pad_width: 1.8 center_pad_height: 1.8 center_pad_h_div: 2 center_pad_v_div: 2 paste_margin_ratio: -0.2 thermal_vias: false QFN-48-1EP_6x6mm_Pitch0.4mm: description: "48-Lead Plastic Quad Flat, No Lead Package - 6x6 mm Body [QFN]; see figure 7.2 of https://static.dev.sifive.com/SiFive-FE310-G000-datasheet-v1.0.4.pdf" pkg_width: 6.0 pkg_height: 6.0 pitch: 0.4 n_horz_pads: 12 n_vert_pads: 12 pad_width: 0.65 pad_height: 0.2 pad_h_distance: 5.85 pad_v_distance: 5.85 corner_pads: false center_pad: true center_pad_width: 4.4 center_pad_height: 4.4 center_pad_h_div: 3 center_pad_v_div: 3 paste_margin_ratio: -0.2 thermal_vias: false QFN-48-1EP_7x7mm_P0.5mm_EP5.6x5.6mm: description: "48-Lead Plastic Quad Flat, No Lead Package - 7x7 mm Body [QFN]; see figure 37 of http://www.st.com/resource/en/datasheet/stm32f042k6.pdf" pkg_width: 7.0 pkg_height: 7.0 pitch: 0.5 n_horz_pads: 12 n_vert_pads: 12 pad_width: 0.55 pad_height: 0.3 pad_h_distance: 6.75 pad_v_distance: 6.75 corner_pads: false center_pad: true center_pad_width: 5.6 center_pad_height: 5.6 center_pad_h_div: 4 center_pad_v_div: 4 paste_margin_ratio: -0.1 thermal_vias: false QFN-44-1EP_9x9mm_Pitch0.65mm: description: "44-Lead Plastic Quad Flat, No Lead Package - 9x9 mm Body [QFN]; see section 10.3 of https://www.parallax.com/sites/default/files/downloads/P8X32A-Propeller-Datasheet-v1.4.0_0.pdf" pkg_width: 9.0 pkg_height: 9.0 pitch: 0.65 n_horz_pads: 11 n_vert_pads: 11 pad_width: 0.60 pad_height: 0.33 pad_h_distance: 8.6 pad_v_distance: 8.6 corner_pads: false center_pad: true center_pad_width: 7.5 center_pad_height: 7.5 center_pad_h_div: 2 center_pad_v_div: 2 paste_margin_ratio: -0.14666666666666667 thermal_vias: false QFN-44-1EP_9x9mm_Pitch0.65mm_ThermalVias: description: "44-Lead Plastic Quad Flat, No Lead Package - 9x9 mm Body [QFN] with thermal vias; see section 10.3 of https://www.parallax.com/sites/default/files/downloads/P8X32A-Propeller-Datasheet-v1.4.0_0.pdf" pkg_width: 9.0 pkg_height: 9.0 pitch: 0.65 n_horz_pads: 11 n_vert_pads: 11 pad_width: 0.60 pad_height: 0.33 pad_h_distance: 8.6 pad_v_distance: 8.6 corner_pads: false center_pad: true center_pad_width: 7.5 center_pad_height: 7.5 center_pad_h_div: 2 center_pad_v_div: 2 paste_margin_ratio: -0.14666666666666667 thermal_vias: true via_size: 0.3 QFN-36-1EP_6x6mm_P0.5mm_EP4.1x4.1mm: description: "36-Lead Plastic Quad Flat, No Lead Package - 6x6 mm Body [QFN]; see figure 36 of http://www.st.com/resource/en/datasheet/stm32f101t6.pdf" pkg_width: 6.0 pkg_height: 6.0 pitch: 0.5 n_horz_pads: 9 n_vert_pads: 9 pad_width: 0.75 pad_height: 0.3 pad_h_distance: 5.55 pad_v_distance: 5.55 corner_pads: false center_pad: true center_pad_width: 4.1 center_pad_height: 4.1 center_pad_h_div: 4 center_pad_v_div: 4 paste_margin_ratio: -0.1 thermal_vias: false QFN-76-1EP_9x9mm_P0.4mm_EP3.8x3.8mm: description: "76-Lead Plastic Quad Flat, No Lead Package - 9x9 mm Body [QFN]; see section 3.2 of https://www.marvell.com/documents/bqcwxsoiqfjkcjdjhkvc/" pkg_width: 9.0 pkg_height: 9.0 pitch: 0.4 n_horz_pads: 19 n_vert_pads: 19 pad_width: 1 pad_height: 0.2 pad_h_distance: 8.6 pad_v_distance: 8.6 corner_pads: false center_pad: true center_pad_width: 3.8 center_pad_height: 3.8 center_pad_h_div: 1 center_pad_v_div: 1 paste_margin_ratio: 0 thermal_vias: false ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/MicroSiP.yaml ================================================ Texas_MicroSiP-10-1EP_3.8x3.0mm_P0.6mm_EP0.7x2.9mm_ThermalVia: device_type: 'MicroSiP' library: Package_LGA manufacturer: 'Texas' part_number: 'SIL0010A' size_source: 'http://www.ti.com/lit/ml/mpds579b/mpds579b.pdf' ipc_class: 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3.8 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 lead_width: nominal: 0.3 tolerance: 0.1 lead_len: nominal: 0.65 tolerance: 0.1 # this will result in a pad 0.8x0.45 (max tolerance + placement_tolerance) lead_center_pos_x: nominal: 1.525 tolerance: 0 EP_size_x_min: 0.6 EP_size_x_max: 0.8 EP_size_y_min: 2.8 EP_size_y_max: 3.0 EP_center_x: nominal: -0.175 EP_center_y: nominal: 0 #EP_paste_coverage: 0.86 EP_num_paste_pads: [1, 3] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [1, 3] grid: 1.03 drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [1, 3] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.86 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.6 num_pins_x: 0 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '' include_suffix_in_3dpath: 'False' Texas_MicroSiP-8-1EP_2.8x3.0mm_P0.65mm_EP1.9x1.1mm_ThermalVia: device_type: 'MicroSiP' library: Package_LGA manufacturer: 'Texas' part_number: 'SIL0008D' size_source: 'http://www.ti.com/lit/ds/symlink/tps82130.pdf#page=19' ipc_class: 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.7 maximum: 2.9 body_size_y: minimum: 2.9 maximum: 3.1 lead_width: minimum: 0.38 maximum: 0.42 lead_len: minimum: 0.48 maximum: 0.52 lead_to_edge: nominal: 0.1 tolerance: 0 EP_size_x: minimum: 1.0 maximum: 1.2 EP_size_y: minimum: 1.8 maximum: 2.0 EP_num_paste_pads: [1, 3] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [1, 3] grid: 0.75 drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [1, 3] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '' include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/csp.yaml ================================================ LFCSP-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'Analog' #part_number: 'CP-32-2' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/414143737956480539664569cp_32_2.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 body_height: minimum: 0.8 nominal: 0.85 maximum: 1 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.95 nominal: 3.1 maximum: 3.25 EP_size_y: minimum: 2.95 nominal: 3.1 maximum: 3.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 #EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-48-1EP_7x7mm_P0.5mm_EP4.1x4.1mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp_48_5.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'LFCSP-{pincount}-1EP_{size_x:g}x{size_x:g}mm_P{pitch:g}mm_EP{ep_size_x:g}x{ep_size_x:g}mm{vias:s}' body_size_x: nominal: 7 tolerance: 0 body_size_y: nominal: 7 tolerance: 0 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.3 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 3.95 nominal: 4.1 maximum: 4.25 EP_size_y: minimum: 3.95 nominal: 4.1 maximum: 4.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-72-1EP_10x10mm_Pitch0.5mm_EP5.3x5.3mm_ThermalVias: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1452_1451_1450.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 9.9 nominal: 10.0 maximum: 10.1 body_size_y: minimum: 9.9 nominal: 10.0 maximum: 10.1 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 5.15 nominal: 5.3 maximum: 5.45 EP_size_y: minimum: 5.15 nominal: 5.3 maximum: 5.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 18 num_pins_y: 18 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/dfn.yaml ================================================ DFN-6-1EP_1.2x1.2mm_P0.4mm_EP0.3x0.94mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.onsemi.com/pub/Collateral/NCP133-D.PDF' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. #body_size_x_min: 2.85 body_size_x: nominal: 1.2 tolerance: 0 #body_size_x_max: 3.15 #body_size_y_min: 2.85 body_size_y: nominal: 1.2 tolerance: 0 #body_size_y_max: 3.15 lead_to_edge: nominal: 0.05 tolerance: 0 lead_width_min: 0.13 lead_width_max: 0.23 lead_len_min: 0.15 lead_len_max: 0.25 EP_size_x_min: 0.2 EP_size_x_max: 0.4 EP_size_y_min: 0.84 EP_size_y_max: 1.04 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] pitch: 0.4 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-6-1EP_2x1.8mm_P0.5mm_EP1.2x1.6mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.diodes.com/assets/Package-Files/U-DFN2018-6.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2 minimum: 1.95 maximum: 2.075 body_size_y: nominal: 1.8 minimum: 1.750 maximum: 1.875 lead_width_min: 0.15 lead_width_max: 0.25 lead_len_min: 0.2 lead_len_max: 0.3 EP_size_x: 1.2 EP_size_y: 1.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] heel_reduction: 0.1 #for relatively large EP pads (increase clearance) pitch: 0.5 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-6-1EP_2x2mm_P0.5mm_EP0.6x1.37mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-dfn/05081703_C_DC6.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2 minimum: 1.9 maximum: 2.1 body_size_y: nominal: 2 minimum: 1.9 maximum: 2.1 lead_width_min: 0.2 lead_width_max: 0.3 lead_len_min: 0.3 lead_len_max: 0.5 EP_size_x: 0.6 EP_size_y: 1.37 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) pitch: 0.5 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-6-1EP_3x2mm_P0.5mm_EP1.65x1.35mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-dfn/(DCB6)%20DFN%2005-08-1715%20Rev%20A.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: 3 body_size_y: 2 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: 1.65 EP_size_y: 1.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] heel_reduction: 0.0 #for relatively large EP pads (increase clearance) pitch: 0.5 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-6-1EP_3x3mm_P1mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.silabs.com/documents/public/data-sheets/Si7020-A20.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. #body_size_x_min: 2.85 body_size_x: 3.0 #body_size_x_max: 3.15 #body_size_y_min: 2.85 body_size_y: 3.0 #body_size_y_max: 3.15 lead_width_min: 0.35 lead_width_max: 0.45 lead_len_min: 0.35 lead_len_max: 0.45 EP_size_x_min: 1.4 EP_size_x: 1.5 EP_size_x_max: 1.6 EP_size_y_min: 2.3 EP_size_y: 2.4 EP_size_y_max: 2.5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 1.0 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' MLF-6-1EP_1.6x1.6mm_P0.5mm_EP0.5x1.26mm: device_type: 'MLF' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/mic5353.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 1.6 tolerance: 0.05 body_size_y: nominal: 1.6 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.35 tolerance: 0.05 EP_size_x: nominal: 0.5 tolerance: 0.05 EP_size_y: nominal: 1.26 tolerance: 0.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-8-1EP_2x2mm_P0.5mm_EP0.6x1.2mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.qorvo.com/products/d/da001879' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2 tolerance: 0.05 body_size_y: nominal: 2 tolerance: 0.05 overall_height: minimum: 0.8 maximum: 1 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.35 tolerance: 0.05 EP_size_x: nominal: 0.60 tolerance: 0.05 # EP_size_x_overwrite: 0.7 EP_size_y: nominal: 1.20 tolerance: 0.05 # EP_size_y_overwrite: 1.3 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-8-1EP_2x2mm_P0.5mm_EP0.7x1.3mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.onsemi.com/pub/Collateral/NUF4401MN-D.PDF#page=6' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2 tolerance: 0 body_size_y: nominal: 2 tolerance: 0 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.25 maximum: 0.45 EP_size_x: minimum: 0.5 maximum: 0.7 EP_size_x_overwrite: 0.7 EP_size_y: minimum: 1.1 maximum: 1.3 EP_size_y_overwrite: 1.3 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-8-1EP_3x2mm_P0.5mm_EP0.56x2.15mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/2451fg.pdf#page=17' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 0.56 tolerance: 0.05 # EP_size_x_overwrite: 0.56 EP_size_y: nominal: 2.15 tolerance: 0.05 # EP_size_y_overwrite: 2.15 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) # DFN-8-1EP_2x2mm_P0.5mm_EP0.8x1.2mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.onsemi.com/pub/Collateral/NB3N551-D.PDF#page=7' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2 tolerance: 0 body_size_y: nominal: 2 tolerance: 0 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.25 maximum: 0.35 EP_size_x: minimum: 0.7 maximum: 0.9 EP_size_x_overwrite: 0.9 EP_size_y: minimum: 1.1 maximum: 1.3 EP_size_y_overwrite: 1.3 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-8-1EP_2x2mm_P0.5mm_EP0.9x1.5mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8127-AVR-8-bit-Microcontroller-ATtiny4-ATtiny5-ATtiny9-ATtiny10_Datasheet.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2 tolerance: 0.05 body_size_y: nominal: 2 tolerance: 0.05 lead_width: minimum: 0.2 maximum: 0.3 lead_len: nominal: 0.3 tolerance: 0.1 EP_size_x: 0.9 EP_size_y: 1.5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] heel_reduction: 0.025 #for relatively large EP pads (increase clearance) pitch: 0.5 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-8-1EP_2x3mm_P0.5mm_EP1.7x1.4mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/8L_DFN_2x3x0_9_MC_C04-123C.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 3 tolerance: 0 body_size_y: nominal: 2 tolerance: 0 overall_height: minimum: 0.8 maximum: 1 nominal: 0.9 lead_width: minimum: 0.2 maximum: 0.3 nominal: 0.25 lead_len: minimum: 0.3 maximum: 0.5 nominal: 0.4 EP_size_x: minimum: 1.5 maximum: 1.75 EP_size_x_overwrite: 1.7 EP_size_y: minimum: 1.3 maximum: 1.55 EP_size_y_overwrite: 1.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-8-1EP_2x2mm_P0.5mm_EP0.9x1.6mm: device_type: 'DFN' size_source: 'https://www.st.com/resource/en/datasheet/lm2903.pdf#page=16' body_size_x: 1.85 .. 2.00 .. 2.15 body_size_y: 1.85 .. 2.00 .. 2.15 lead_width: 0.18 .. 0.25 .. 0.30 lead_len: 0.20 .. 0.30 .. 0.50 # only max given in DS. # Min and nominal from JEDEC MO-229 V2020D-3 EP_size_x: 0.75 .. 0.9 .. 1.00 EP_size_y: 1.45 .. 1.6 .. 1.70 pitch: 0.5 num_pins_x: 0 num_pins_y: 4 DFN-8-1EP_3x3mm_P0.5mm_EP1.65x2.38mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/4320fb.pdf#page=10' # ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 pitch: 0.5 num_pins_x: 0 num_pins_y: 4 EP_size_x: 1.65 EP_size_y: 2.38 thermal_vias: count: [2, 3] drill: 0.2 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] paste_avoid_via: False DFN-8-1EP_3x3mm_P0.65mm_EP1.7x2.05mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ixysic.com/home/pdfs.nsf/www/IX4426-27-28.pdf/$file/IX4426-27-28.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 3 tolerance: 0 body_size_y: nominal: 3 tolerance: 0 lead_width: nominal: 0.3 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.05 EP_size_x: 1.7 EP_size_y: 2.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) pitch: 0.65 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-8-1EP_4x4mm_P0.8mm_EP2.3x3.24mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.st.com/resource/en/datasheet/ld1086.pdf#page=35' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 3.90 nominal: 4 maximum: 4.10 body_size_y: minimum: 3.90 nominal: 4 maximum: 4.10 lead_width: minimum: 0.23 nominal: 0.30 maximum: 0.38 lead_len: minumum: 0.4 nominal: 0.5 maximum: 0.6 EP_size_x: minimum: 2.05 nominal: 2.20 maximum: 2.30 EP_size_y: minimum: 2.82 nominal: 3 maximum: 3.23 EP_size_x_overwrite: 2.30 EP_size_y_overwrite: 3.24 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) pitch: 0.80 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) DFN-10-1EP_3x3mm_P0.5mm_EP1.7x2.5mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.monolithicpower.com/pub/media/document/MPQ2483_r1.05.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 2.9 maximum: 3.1 body_size_y: minimum: 2.9 maximum: 3.1 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 1.45 maximum: 17.5 EP_size_x_overwrite: 1.7 EP_size_y: minimum: 2.25 maximum: 2.55 EP_size_y_overwrite: 2.5 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 5 DFN-10-1EP_3x3mm_P0.5mm_EP1.65x2.38mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/3471fb.pdf#page=15' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 3.0 tolerance: 0.1 body_size_y: nominal: 3.0 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.38 tolerance: 0.1 EP_size_x: nominal: 1.65 tolerance: 0.05 EP_size_y: nominal: 2.38 tolerance: 0.05 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 #EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 5 Balun_Johanson_0900PC15J0013: device_type: 'DFN' manufacturer: 'Johanson' part_number: '0900PC15J0013' library: 'RF_Converter' size_source: 'https://www.johansontechnology.com/datasheets/0900PC15J0013/0900PC15J0013.pdf' custom_name_format: 'Balun_Johanson_0900PC15J0013' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 1.25 tolerance: 0.2 body_size_y: nominal: 2 tolerance: 0.2 lead_width: nominal: 0.25 tolerance: 0.1 lead_len: minimum: 0.05 nominal: 0.15 # should be 0.2mm by specs, but 0.8mm between pads is required. maximum: 0.15 # should be 0.3mm by specs, but 0.8mm between pads is required. # lead_to_edge: 0.1 pitch: 0.50 num_pins_x: 1 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: pad_length_addition: -0.1 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) Texas_S-PDSO-N10_EP1.2x2.0mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/tps7a91.pdf#page=30' custom_name_format: 'Texas_S-PDSO-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 2.4 maximum: 2.6 body_size_y: minimum: 2.4 maximum: 2.6 overall_height: minimum: 0.7 maximum: 0.8 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x: minimum: 1.1 maximum: 1.3 EP_size_y: minimum: 1.9 maximum: 2.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) WDFN-8-1EP_2x2mm_P0.5mm_EP0.8x1.2mm: device_type: 'WDFN' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/20005474E.pdf#page=25' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: 2.0 body_size_y: 2.0 lead_width: 0.25 +/- 0.05 lead_len: 0.3 +/- 0.05 EP_size_x: minimum: 0.7 nominal: 0.8 maximum: 0.9 EP_size_y: minimum: 1.1 nominal: 1.2 maximum: 1.3 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 WDFN-8-1EP_3x2mm_P0.5mm_EP1.3x1.4mm: device_type: 'WDFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/8L_TDFN_2x3_MNY_C04-0129E-MNY.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 3.0 tolerance: 0 body_size_y: nominal: 2.0 tolerance: 0 lead_width_min: 0.2 lead_width_max: 0.3 lead_len_min: 0.25 lead_len_max: 0.45 EP_size_x: 1.3 EP_size_y: 1.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WDFN-8-1EP_4x3mm_P0.65mm_EP2.4x1.8mm: device_type: 'WDFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.onsemi.com/pub/Collateral/509AF.PDF' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 4.0 tolerance: 0 body_size_y: nominal: 3.0 tolerance: 0 lead_width_min: 0.2 lead_width_max: 0.3 lead_len_min: 0.45 lead_len_max: 0.55 EP_size_x: minimum: 2.3 maximum: 2.5 EP_size_y: minimum: 1.7 maximum: 1.9 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 #EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WDFN-12-1EP_3x3mm_P0.45mm_EP1.7x2.5mm: device_type: 'WDFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.diodes.com/assets/Datasheets/PAM2306.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 2.95 maximum: 3.05 body_size_y: minimum: 2.95 maximum: 3.05 lead_width_min: 0.15 lead_width_max: 0.25 lead_len_min: 0.35 lead_len_max: 0.45 EP_size_x: 1.7 EP_size_y: 2.5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.45 num_pins_x: 0 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Broadcom_DFN-6_2.0x2.0mm: device_type: 'DFN' size_source: 'https://docs.broadcom.com/docs/AV02-4755EN' library: 'OptoDevice' manufacturer: 'Broadcom' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: nominal: 2 tolerance: 0.1 body_size_y: nominal: 2 tolerance: 0.1 overall_height: nominal: 0.65 tolerance: 0.1 lead_width: nominal: 0.3 tolerance: 0.05 lead_len: nominal: 0.75 tolerance: 0.15 pitch: 0.65 num_pins_x: 0 num_pins_y: 3 Texas_VSON-HR_1.5x2mm_P0.5mm: device_type: 'VSON-HR' size_source: 'http://www.ti.com/lit/ds/symlink/tps62823.pdf#page=29' manufacturer: 'Texas' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: minimum: 1.4 maximum: 1.6 body_size_y: minimum: 1.9 maximum: 2.1 overall_height: maximum: 1 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.4 pitch: 0.5 num_pins_x: 0 num_pins_y: 4 TDFN-6-1EP_2.5x2.5mm_P0.65mm_EP1.3x2mm: device_type: 'TDFN' size_source: 'http://www.nve.com/Downloads/ab3.pdf' body_size_x: 2.5 +/-0.1 body_size_y: 2.5 +/-0.1 overall_height: 0.8 lead_width: 0.3 +/-0.05 lead_len: 0.3 +/-0.05 EP_size_x: 1.3 +/-0.05 EP_size_y: 2.0 +/-0.05 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) TDFN-14-1EP_3x3mm_P0.4mm_EP1.78x2.35mm: device_type: 'TDFN' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0137.PDF (T1433-2C)' body_size_x: 2.9 .. 3.0 .. 3.1 body_size_y: 2.9 .. 3.0 .. 3.1 overall_height: 0.7 .. 0.75 .. 0.8 lead_width: 0.2 +/-0.05 lead_len: 0.2 .. 0.3 .. 0.4 EP_size_x: 1.7 +/- 0.1 EP_size_y: 2.3 +/-0.1 EP_size_x_overwrite: 1.78 EP_size_y_overwrite: 2.35 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 0 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) TDFN-10-1EP_2x3mm_P0.5mm_EP2.0x0.8mm: device_type: 'TDFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0429.PDF' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 2.0 tolerance: 0.1 body_size_y: nominal: 3.0 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.30 tolerance: 0.1 EP_size_x: nominal: 0.9 tolerance: 0.1 EP_size_y: nominal: 2.0 tolerance: 0.1 EP_num_paste_pads: [1, 2] thermal_vias: count: [1, 2] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [1, 2] #paste_between_vias: 1 #paste_rings_outside: 1 #EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 5 TDFN-8-1EP_2x2mm_P0.5mm_EP0.8x1.30mm: device_type: 'TDFN' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0168.PDF' body_size_x: 2.0 +/-0.1 body_size_y: 2.0 +/-0.1 overall_height: 0.75 lead_width: 0.25 +/-0.05 lead_len: 0.3 +/-0.1 EP_size_x: 0.8 +/-0.1 EP_size_y: 1.20 +/-0.1 EP_size_y_overwrite: 1.30 +/-0.1 EP_num_paste_pads: [2, 2] pitch: 0.50 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) TDFN-8-1EP_3x2mm_P0.5mm_EP1.3x1.4mm: device_type: 'TDFN' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/MCP6V66-Family-Data-Sheet-DS20006266A.pdf#page=35' body_size_x: 3.0 body_size_y: 2.0 overall_height: 0.75 lead_width: 0.25 +/-0.05 lead_len: 0.3 +0.15 -0.05 EP_size_x: 1.3 +/-0.05 EP_size_y: 1.4 +/-0.05 #EP_size_y_overwrite: 1.30 +/-0.1 EP_num_paste_pads: [2, 2] pitch: 0.50 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) TDFN-8-1EP_3x2mm_P0.5mm_EP1.4x1.4mm: device_type: 'TDFN' size_source: 'http://ww1.microchip.com/downloads/en/devicedoc/20005514a.pdf#page=35' body_size_x: 3.00 body_size_y: 2.00 overall_height: minimum: 0.70 nominal: 0.75 maximum: 0.80 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.25 nominal: 0.30 maximum: 0.45 EP_size_x: 1.20 .. 1.60 EP_size_y: 1.20 .. 1.60 EP_num_paste_pads: [2, 2] pitch: 0.50 num_pins_x: 0 num_pins_y: 4 DFN-14_1.35x3.5mm_P0.5mm: device_type: 'DFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://m.littelfuse.com/~/media/electronics/datasheets/tvs_diode_arrays/littelfuse_tvs_diode_array_sp3012_datasheet.pdf.pdf#page=7' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 1.25 nominal: 1.35 maximum: 1.45 body_size_y: minimum: 3.4 nominal: 3.5 maximum: 3.6 overall_height: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.25 nominal: 0.3 maximum: 0.35 pitch: 0.5 num_pins_x: 0 num_pins_y: 7 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/hvson8.yaml ================================================ HVSON-8-1EP_4x4mm_P0.8mm_EP2.2x3.1mm: device_type: 'HVSON' library: Package_SON size_source: 'https://www.nxp.com/docs/en/data-sheet/PCF8523.pdf (page 57)' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: minimum: 1.00 lead_width: minimum: 0.30 maximum: 0.40 lead_len: minimum: 0.4 maximum: 0.65 EP_size_x: minimum: 2.05 maximum: 2.35 EP_size_y: minimum: 2.95 maximum: 3.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.8 num_pins_x: 0 num_pins_y: 4 HVSON-8-1EP_3x3mm_P0.65mm_EP1.6x2.4mm: device_type: 'HVSON' library: Package_SON size_source: 'https://www.nxp.com/docs/en/data-sheet/TJA1051.pdf#page=16' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 2.9 nominal: 3.0 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3.0 maximum: 3.1 overall_height: minimum: 0.8 nominal: 0.85 maximum: 1.0 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.35 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 1.55 nominal: 1.6 maximum: 1.65 EP_size_y: minimum: 2.35 nominal: 2.4 maximum: 2.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.65 num_pins_x: 0 num_pins_y: 4 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/lfcsp.yaml ================================================ LFCSP-8-1EP_3x3mm_P0.5mm_EP1.74x1.45mm: device_type: 'LFCSP' library: Package_CSP # manufacturer: 'Analog' # part_number: 'CP-8-13' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp-8/CP_8_13.pdf' # ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. #body_size_x_min: 2.85 body_size_x: nominal: 3.0 tolerance: 0.1 #body_size_x_max: 3.15 #body_size_y_min: 2.85 body_size_y: nominal: 3.0 tolerance: 0.1 #body_size_y_max: 3.15 lead_to_edge: nominal: 0.0 tolerance: 0.0 lead_width_min: 0.2 lead_width_max: 0.3 lead_len_min: 0.3 lead_len_max: 0.5 EP_size_x_min: 1.35 EP_size_x_max: 1.55 EP_size_y_min: 1.64 EP_size_y_max: 1.84 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 0 num_pins_y: 4 LFCSP-WD-8-1EP_3x3mm_P0.65mm_EP1.6x2.44mm: device_type: 'LFCSP-WD' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/CP_8_19.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 body_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: maximum: 0.35 nominal: 0.30 minimum: 0.20 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: maximum: 1.70 nominal: 1.60 minimum: 1.50 EP_size_y: maximum: 2.54 nominal: 2.44 minimum: 2.34 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 3] drill: 0.3 # min_annular_ring: 0.15 #paste_via_clearance: 0.1 EP_num_paste_pads: [2, 3] #paste_between_vias: 1 #paste_rings_outside: 1 #EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-WD-10-1EP_3x3mm_P0.5mm_EP1.64x2.38mm: device_type: 'LFCSP-WD' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp-10/CP_10_9.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 body_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: maximum: 0.30 nominal: 0.25 minimum: 0.20 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: maximum: 1.74 nominal: 1.64 minimum: 1.49 EP_size_y: maximum: 2.48 nominal: 2.38 minimum: 2.23 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 3] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-16-1EP_3x3mm_P0.5mm_EP1.3x1.3mm: device_type: 'LFCSP' library: Package_CSP # manufacturer: 'Analog' # part_number: 'CP-16-21' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp-16/CP_16_21.pdf' body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 body_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: maximum: 0.30 nominal: 0.23 minimum: 0.18 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: maximum: 1.45 nominal: 1.30 minimum: 1.15 EP_size_y: maximum: 1.45 nominal: 1.30 minimum: 1.15 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.3 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 LFCSP-16-1EP_3x3mm_P0.5mm_EP1.6x1.6mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp-16/CP_16_22.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 body_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: maximum: 0.30 nominal: 0.23 minimum: 0.18 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: maximum: 1.75 nominal: 1.60 minimum: 1.45 EP_size_y: maximum: 1.75 nominal: 1.60 minimum: 1.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-16-1EP_3x3mm_P0.5mm_EP1.7x1.7mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/HMC7992.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 body_height: minimum: 0.75 nominal: 0.85 maximum: 0.95 lead_width: maximum: 0.30 nominal: 0.25 minimum: 0.20 lead_len: maximum: 0.35 nominal: 0.30 minimum: 0.25 EP_size_x: maximum: 1.92 nominal: 1.70 minimum: 1.48 EP_size_y: maximum: 1.92 nominal: 1.70 minimum: 1.48 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-16-1EP_4x4mm_P0.65mm_EP2.4x2.4mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp-16/cp-16-40.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 nominal: 4 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4 maximum: 4.1 body_height: minimum: 0.8 nominal: 0.9 maximum: 1.0 lead_width: minimum: 0.27 nominal: 0.33 maximum: 0.39 lead_len: minimum: 0.5 nominal: 0.6 maximum: 0.7 EP_size_x: maximum: 2.55 nominal: 2.40 minimum: 2.25 EP_size_y: maximum: 2.55 nominal: 2.40 minimum: 2.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-20-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp-20/CP_20_8.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 nominal: 4 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4 maximum: 4.1 body_height: minimum: 0.70 nominal: 0.75 maximum: 0.80 lead_width: maximum: 0.30 nominal: 0.25 minimum: 0.18 lead_len: maximum: 0.50 nominal: 0.40 minimum: 0.30 EP_size_x: maximum: 2.75 nominal: 2.60 minimum: 2.35 EP_size_y: maximum: 2.75 nominal: 2.60 minimum: 2.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.70 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-24-1EP_4x4mm_P0.5mm_EP2.3x2.3mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp_24_14.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 nominal: 4 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4 maximum: 4.1 body_height: minimum: 0.70 nominal: 0.75 maximum: 0.80 lead_width: maximum: 0.30 nominal: 0.25 minimum: 0.2 lead_len: maximum: 0.50 nominal: 0.40 minimum: 0.30 EP_size_x: maximum: 2.44 nominal: 2.30 minimum: 2.16 EP_size_y: maximum: 2.44 nominal: 2.30 minimum: 2.16 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.70 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-28-1EP_5x5mm_P0.5mm_EP3.14x3.14mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp-28/CP_28_10.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 4.9 nominal: 5 minimum: 5.1 body_size_y: minimum: 4.9 nominal: 5 minimum: 5.1 body_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: maximum: 0.30 nominal: 0.25 minimum: 0.20 lead_len: minimum: 0.48 nominal: 0.53 maximum: 0.58 EP_size_x: maximum: 3.24 nominal: 3.14 minimum: 3.04 EP_size_y: maximum: 3.24 nominal: 3.14 minimum: 3.04 #EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.70 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LFCSP-64-1EP_9x9mm_P0.5mm_EP5.21x5.21mm: device_type: 'LFCSP' library: Package_CSP #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp_64_7.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 8.9 nominal: 9 minimum: 9.1 body_size_y: minimum: 8.9 nominal: 9 minimum: 9.1 body_height: minimum: 0.8 nominal: 0.85 maximum: 1.0 lead_width: maximum: 0.30 nominal: 0.25 minimum: 0.18 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: maximum: 5.36 nominal: 5.21 minimum: 5.06 EP_size_y: maximum: 5.36 nominal: 5.21 minimum: 5.06 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/lga.yaml ================================================ LGA-16_3x3mm_P0.5mm_LayoutBorder3x5y: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.st.com/resource/en/datasheet/lis331hh.pdf' ipc_class: 'qfn_pull_back' body_size_x_min: 2.85 body_size_x: 3.0 body_size_x_max: 3.15 body_size_y_min: 2.85 body_size_y: 3.0 body_size_y_max: 3.15 lead_width_min: 0.19 lead_width_max: 0.31 lead_to_edge: minimum: 0.04 maximum: 0.16 lead_len_min: 0.29 lead_len_max: 0.41 pitch: 0.5 num_pins_x: 3 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LGA-14_2x2mm_P0.35mm_LayoutBorder3x4y: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' ipc_density: 'least' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.st.com/resource/en/datasheet/lis2dh.pdf' ipc_class: 'qfn_pull_back' body_size_x_min: 1.85 body_size_x: 2.0 body_size_x_max: 2.15 body_size_y_min: 1.85 body_size_y: 2.0 body_size_y_max: 2.15 lead_width_min: 0.2 lead_width_max: 0.2 lead_to_edge: nominal: 0.1 lead_len_min: 0.275 lead_len_max: 0.275 pitch: 0.35 num_pins_x: 3 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LGA-14_3x2.5mm_P0.5mm_LayoutBorder3x4y: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.st.com/resource/en/datasheet/lsm6ds3.pdf' ipc_class: 'qfn_pull_back' body_size_x_min: 2.9 body_size_x: 3.0 body_size_x_max: 3.1 body_size_y_min: 2.4 body_size_y: 2.5 body_size_y_max: 2.6 lead_width_min: 0.15 lead_width_max: 0.35 lead_to_edge: nominal: 0.1 lead_len_min: 0.35 lead_len_max: 0.55 pitch: 0.5 num_pins_x: 3 num_pins_y: 4 chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LGA-14_3x5mm_P0.8mm_LayoutBorder1x6y: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.st.com/resource/en/datasheet/lsm303dlhc.pdf' ipc_class: 'qfn_pull_back' body_size_x_min: 2.85 body_size_x: 3.0 body_size_x_max: 3.15 body_size_y_min: 4.85 body_size_y: 5.0 body_size_y_max: 5.15 lead_width_min: 0.5 lead_width_max: 0.5 lead_to_edge: nominal: 0.1 lead_len_min: 0.8 lead_len_max: 0.8 pitch: 0.8 num_pins_x: 1 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' LGA-16_4x4mm_P0.65mm_LayoutBorder4x4y: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.st.com/resource/en/datasheet/l3gd20.pdf' ipc_class: 'qfn_pull_back' body_size_x_min: 3.85 body_size_x: 4.0 body_size_x_max: 4.15 body_size_y_min: 3.85 body_size_y: 4.0 body_size_y_max: 4.15 lead_width_min: 0.3 lead_width_max: 0.3 lead_to_edge: nominal: 0.1 lead_len_min: 0.4 lead_len_max: 0.4 pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' NXP-8_3x5mm_P1.25mm_LayoutBorder2x4y_H1.2mm: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' manufacturer: 'NXP' #part_number: 'MPL115A1' size_source: 'https://www.nxp.com/docs/en/data-sheet/MPL115A1.pdf#page=15' body_size_x: nominal: 3 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 body_height: maximum: 1.2 lead_width: nominal: 0.5 tolerance: 0.05 lead_center_pos_x: nominal: 1 tolerance: 0 lead_len: nominal: 0.8 tolerance: 0.05 pitch: 1.25 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '_H1.2mm' #include_suffix_in_3dpath: 'False' NXP-8_3x5mm_P1.25mm_LayoutBorder2x4y_H1.1mm: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' manufacturer: 'NXP' #part_number: 'MPL3115A2' size_source: 'https://www.nxp.com/docs/en/data-sheet/MPL3115A2.pdf#page=42' body_size_x: nominal: 3 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 body_height: maximum: 1.1 tolerance: 0.1 lead_width: nominal: 0.5 tolerance: 0.05 lead_center_pos_x: nominal: 1 tolerance: 0 lead_len: nominal: 0.8 tolerance: 0.05 pitch: 1.25 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '_H1.1mm' #include_suffix_in_3dpath: 'False' Bosch_LGA-8_3x3mm_P0.8mm: device_type: 'LGA' library: Package_LGA use_name_format: 'LGA' manufacturer: 'Bosch' #part_number: 'mpn' size_source: 'https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME680-DS001-00.pdf#page=44' ipc_class: 'qfn_pull_back' body_size_x_min: 2.95 body_size_x: 3.0 body_size_x_max: 3.05 body_size_y_min: 2.95 body_size_y: 3.0 body_size_y_max: 3.05 lead_width_min: 0.37 lead_width_max: 0.43 lead_to_edge: minimum: 0.05 maximum: 0.15 lead_len_min: 0.37 lead_len_max: 0.43 pitch: 0.8 num_pins_x: 4 num_pins_y: 0 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '_ClockwisePinNumbering' #include_suffix_in_3dpath: 'False' ST_HLGA-10_2.5x2.5mm_P0.6mm: device_type: 'HLGA' library: Package_LGA use_name_format: 'LGA' manufacturer: 'ST' #part_number: 'mpn' size_source: 'https://www.st.com/resource/en/datasheet/lps25hb.pdf#page=46' ipc_class: 'qfn_pull_back' body_size_x: nominal: 2.5 tolerance: 0.1 body_size_y: nominal: 2.5 tolerance: 0.1 lead_width: nominal: 0.3 tolerance: 0.05 lead_center_pos_x: nominal: 0.92 tolerance: 0 lead_center_pos_y: nominal: 0.92 tolerance: 0 lead_len: nominal: 0.45 tolerance: 0.05 pitch: 0.6 num_pins_x: 3 num_pins_y: 2 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_ClockwisePinNumbering' #include_suffix_in_3dpath: 'False' Broadcom_LGA-8_2.0x2.0mm: device_type: 'LGA' size_source: 'https://docs.broadcom.com/docs/AV02-4755EN' library: 'OptoDevice' manufacturer: 'Broadcom' ipc_class: 'qfn_pull_back' body_size_x: nominal: 2 tolerance: 0.1 body_size_y: nominal: 2 tolerance: 0.1 overall_height: nominal: 0.34 tolerance: 0.1 lead_width: nominal: 0.31 tolerance: 0.1 lead_len: nominal: 0.35 tolerance: 0.1 lead_to_edge: nominal: 0.05 pitch: 0.53 num_pins_x: 0 num_pins_y: 4 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/oscillator.yaml ================================================ Oscillator_SMD_Silicon_Labs_LGA-6_2.5x3.2mm_P1.25mm: device_type: 'LGA' library: Oscillator fp_name_prefix: Oscillator_SMD manufacturer: 'Silicon_Labs' #part_number: '' size_source: 'https://www.silabs.com/documents/public/data-sheets/si512-13.pdf' ipc_class: 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 2.5 tolerance: 0 body_size_y: nominal: 3.2 tolerance: 0 lead_width: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_len: minimum: 0.65 nominal: 0.7 maximum: 0.75 lead_center_to_center_x: nominal: 1.65 tolerance: 0 pitch: 1.25 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '' # include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/hvqfn.yaml ================================================ HVQFN-16-1EP_3x3mm_P0.5mm_EP1.5x1.5mm: device_type: 'HVQFN' #manufacturer: 'NXP' #part_number: 'SOT758-1' size_source: 'https://www.nxp.com/docs/en/package-information/SOT758-1.pdf' ipc_class: 'qfn' body_size_x: minimum: 2.9 nominal: 3.0 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3.0 maximum: 3.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 1.45 maximum: 1.75 EP_size_y: minimum: 1.45 maximum: 1.75 EP_size_x_overwrite: 1.5 EP_size_y_overwrite: 1.5 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 4 num_pins_y: 4 HVQFN-24-1EP_4x4mm_P0.5mm_EP2.5x2.5mm: device_type: 'HVQFN' size_source: 'https://www.nxp.com/docs/en/package-information/SOT616-3.pdf' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: minimum: 3.9 nominal: 4.0 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4.0 maximum: 4.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 2.45 maximum: 2.75 EP_size_y: minimum: 2.45 maximum: 2.75 EP_size_x_overwrite: 2.5 EP_size_y_overwrite: 2.5 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 paste_via_clearance: 0.1 EP_paste_coverage: 0.55 pitch: 0.5 num_pins_x: 6 num_pins_y: 6 HVQFN-24-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'HVQFN' size_source: 'https://www.nxp.com/docs/en/package-information/SOT616-3.pdf' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: minimum: 3.9 nominal: 4.0 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4.0 maximum: 4.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 2.45 maximum: 2.75 EP_size_y: minimum: 2.45 maximum: 2.75 EP_num_paste_pads: [3, 3] thermal_vias: count: [3, 3] drill: 0.2 paste_via_clearance: 0.1 EP_paste_coverage: 0.55 pitch: 0.5 num_pins_x: 6 num_pins_y: 6 HVQFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm: device_type: 'HVQFN' size_source: 'https://www.nxp.com/docs/en/package-information/SOT617-1.pdf' ipc_class: 'qfn' body_size_x: minimum: 4.9 nominal: 5.0 maximum: 5.1 body_size_y: minimum: 4.9 nominal: 5.0 maximum: 5.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 2.95 maximum: 3.25 EP_size_y: minimum: 2.95 maximum: 3.25 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 paste_via_clearance: 0.1 EP_paste_coverage: 0.55 pitch: 0.5 num_pins_x: 8 num_pins_y: 8 HVQFN-40-1EP_6x6mm_P0.5mm_EP4.1x4.1mm: device_type: 'HVQFN' size_source: 'https://www.nxp.com/docs/en/package-information/SOT618-1.pdf' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: minimum: 5.9 nominal: 6.0 maximum: 6.1 body_size_y: minimum: 5.9 nominal: 6.0 maximum: 6.1 overall_height: minimum: 0.8 nominal: 0.85 maximum: 1 lead_width: minimum: 0.18 nominal: 0.21 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 3.95 maximum: 4.25 EP_size_y: minimum: 3.95 maximum: 4.25 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 paste_via_clearance: 0.1 EP_paste_coverage: 0.6 pitch: 0.5 num_pins_x: 10 num_pins_y: 10 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-1x.yaml ================================================ QFN-12-1EP_3x3mm_P0.5mm_EP1.6x1.6mm: device_type: 'QFN' size_source: 'https://www.nxp.com/docs/en/data-sheet/MMZ09332B.pdf' ipc_class: 'qfn' body_size_x: nominal: 3 body_size_y: nominal: 3 overall_height: minimum: 0.8 maximum: 0.9 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 1.40 maximum: 1.60 EP_size_y: minimum: 1.40 maximum: 1.60 EP_size_x_overwrite: 1.6 EP_size_y_overwrite: 1.6 EP_num_paste_pads: [2, 2] thermal_vias: count: [3,3] drill: 0.2 paste_via_clearance: 0.1 EP_num_paste_pads: [3, 3] EP_paste_coverage: 0.75 paste_avoid_via: False pitch: 0.5 num_pins_x: 3 num_pins_y: 3 QFN-12-1EP_3x3mm_P0.5mm_EP1.65x1.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_12_%2005-08-1855.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 1.55 nominal: 1.65 maximum: 1.75 EP_size_y: minimum: 1.55 nominal: 1.65 maximum: 1.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 3 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_3x3mm_P0.5mm_EP1.45x1.45mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://cds.linear.com/docs/en/datasheet/37551fd.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: 1.45 EP_size_y: 1.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_3x3mm_P0.5mm_EP1.7x1.7mm: device_type: 'QFN' ipc_class: 'qfn' size_source: 'https://www.st.com/resource/en/datasheet/tsv521.pdf' body_size_x: minimum: 2.9 nominal: 3.0 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3.0 maximum: 3.1 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: 1.7 EP_size_y: 1.7 heel_reduction: 0.05 #for relatively large EP pads (increase clearance) EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 4 num_pins_y: 4 QFN-16-1EP_3x3mm_P0.5mm_EP1.75x1.75mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.onsemi.com/pub/Collateral/NCN4555-D.PDF' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0 body_size_y: nominal: 3 tolerance: 0 overall_height: minimum: 0.7 maximum: 0.8 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 1.65 maximum: 1.85 #EP_size_x_overwrite: 1.75 EP_size_y: minimum: 1.65 maximum: 1.85 #EP_size_y_overwrite: 1.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_3x3mm_P0.5mm_EP1.9x1.9mm: device_type: 'QFN' ipc_class: 'qfn' size_source: 'https://www.nxp.com/docs/en/package-information/98ASA00525D.pdf' body_size_x: nominal: 3.0 body_size_y: nominal: 3.0 overall_height: minimum: 0.5 maximum: 0.65 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.25 maximum: 0.45 EP_size_x: minimum: 1.8 maximum: 2.0 EP_size_y: minimum: 1.8 maximum: 2.0 EP_num_paste_pads: [2, 2] heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 QFN-16-1EP_4x4mm_P0.65mm_EP2.1x2.1mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.thatcorp.com/datashts/THAT_1580_Datasheet.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 nominal: 4 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4 maximum: 4.1 overall_height: nominal: 0.9 tolerance: 0.05 lead_width: minimum: 0.25 maximum: 0.35 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x: 2.1 EP_size_y: 2.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_4x4mm_P0.65mm_EP2.15x2.15mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/4001f.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0.1 body_size_y: nominal: 4 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.3 tolerance: 0.05 lead_len: nominal: 0.55 tolerance: 0.2 EP_size_x: nominal: 2.15 tolerance: 0.1 EP_size_y: nominal: 2.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_4x4mm_P0.5mm_EP2.45x2.45mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.renesas.com/eu/en/www/doc/datasheet/isl8117.pdf#page=22' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: nominal: 0.9 tolerance: 0.1 lead_width: nominal: 0.25 tolerance: [-0.07, 0.05] lead_len: nominal: 0.4 tolerance: 0.01 EP_size_x: nominal: 2.45 tolerance: [-0.15, 0.1] EP_size_y: nominal: 2.45 tolerance: [-0.15, 0.1] # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_4x4mm_P0.65mm_EP2.5x2.5mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=266' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 body_size_y: nominal: 4 overall_height: nominal: 0.9 tolerance: 0.1 lead_width: minimum: 0.25 nominal: 0.30 maximum: 0.35 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 2.50 nominal: 2.65 maximum: 2.80 EP_size_y: minimum: 2.50 nominal: 2.65 maximum: 2.80 EP_size_x_overwrite: 2.5 EP_size_y_overwrite: 2.5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/doc2535.pdf#page=164' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.30 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.55 EP_size_x: minimum: 2.45 nominal: 2.6 maximum: 2.75 EP_size_y: minimum: 2.45 nominal: 2.6 maximum: 2.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_4x4mm_P0.65mm_EP2.7x2.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.allegromicro.com/~/media/Files/Datasheets/A4403-Datasheet.ashx' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.85 nominal: 4 maximum: 4.15 body_size_y: minimum: 3.85 nominal: 4 maximum: 4.15 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: minimum: 0.25 maximum: 0.35 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: 2.7 EP_size_y: 2.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-16-1EP_4x4mm_P0.65mm_EP2.7x2.7mm_PullBack: device_type: 'QFN' #manufacturer: 'AMS' #part_number: 'mpn' size_source: 'https://ams.com/documents/20143/36005/AS5055A_DS000304_2-00.pdf#page=24' ipc_class: 'qfn_pull_back' #'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.35 body_to_inside_lead_edge: minimum: 0.35 nominal: 0.4 maximum: 0.45 lead_to_edge: minimum: 0 maximum: 0.15 EP_size_x: minimum: 2.6 nominal: 2.7 maximum: 2.8 EP_size_y: minimum: 2.6 nominal: 2.7 maximum: 2.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 suffix: '_PullBack' #include_suffix_in_3dpath: 'False' QFN-16-1EP_5x5mm_P0.8mm_EP2.7x2.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.intersil.com/content/dam/Intersil/documents/l16_/l16.5x5.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.28 maximum: 0.40 lead_len: minimum: 0.35 maximum: 0.75 EP_size_x: minimum: 2.55 nominal: 2.7 maximum: 2.85 EP_size_y: minimum: 2.55 nominal: 2.7 maximum: 2.85 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.8 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-20.yaml ================================================ QFN-20-1EP_3x3mm_P0.45mm_EP1.6x1.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/atmel-8235-8-bit-avr-microcontroller-attiny20_datasheet.pdf#page=212' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 overall_height: minimum: 0.75 nominal: 0.8 maximum: 0.85 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 # For backwards compatibility use 1.6mm even though nominal would be 1.55 EP_size_x: minimum: 1.4 nominal: 1.55 maximum: 1.7 EP_size_x_overwrite: 1.6 EP_size_y: minimum: 1.4 nominal: 1.55 maximum: 1.7 EP_size_y_overwrite: 1.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.45 num_pins_x: 5 num_pins_y: 5 chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_3x3mm_P0.4mm_EP1.65x1.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/3553fc.pdf#page=34' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.2 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 1.65 tolerance: 0.1 EP_size_y: nominal: 1.65 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_3x4mm_P0.5mm_EP1.65x2.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_20_05-08-1742.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 4 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 1.65 tolerance: 0.1 EP_size_y: nominal: 2.65 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_4x4mm_P0.5mm_EP2.5x2.5mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=274' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.6 nominal: 2.7 maximum: 2.8 EP_size_x_overwrite: 2.5 EP_size_y: minimum: 2.6 nominal: 2.7 maximum: 2.8 EP_size_y_overwrite: 2.5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/doc2535.pdf#page=164' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.30 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.55 EP_size_x: minimum: 2.45 nominal: 2.6 maximum: 2.75 EP_size_y: minimum: 2.45 nominal: 2.6 maximum: 2.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_4x4mm_P0.5mm_EP2.7x2.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.silabs.com/documents/public/data-sheets/Si5351-B.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 2.65 nominal: 2.7 maximum: 2.75 EP_size_y: minimum: 2.65 nominal: 2.7 maximum: 2.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_3.5x3.5mm_P0.5mm_EP2x2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ml/mpqf239/mpqf239.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.35 maximum: 3.65 body_size_y: minimum: 3.35 maximum: 3.65 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2 EP_size_y: nominal: 2 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' MLF-20-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'MLF' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/doc8246.pdf#page=263' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.30 lead_len: minimum: 0.35 nominal: 0.45 maximum: 0.55 EP_size_x: minimum: 2.45 nominal: 2.6 maximum: 2.75 EP_size_y: minimum: 2.45 nominal: 2.6 maximum: 2.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_4x5mm_P0.5mm_EP2.65x3.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_20_05-08-1711.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0.1 body_size_y: nominal: 5 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: minimum: 2.55 nominal: 2.65 maximum: 2.75 EP_size_y: minimum: 3.55 nominal: 3.65 maximum: 3.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.55 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-20-1EP_5x5mm_P0.65mm_EP3.35x3.35mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=276' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.35 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 3.15 nominal: 3.25 maximum: 3.35 # For backwards compatibility use maximum size for EP EP_size_x_overwrite: 3.35 EP_size_y: minimum: 3.15 nominal: 3.25 maximum: 3.35 EP_size_y_overwrite: 3.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-24.yaml ================================================ LFCSP-24-1EP_4x4mm_P0.5mm_EP2.5x2.5mm: device_type: 'LFCSP' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/lfcspcp/cp_24_7.pdf' ipc_class: 'qfn' # 'qfn_pull_back' library: 'Package_CSP' body_size_x: minimum: 3.9 nominal: 4 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4 maximum: 4.1 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.45 nominal: 2.5 maximum: 2.65 EP_size_y: minimum: 2.45 nominal: 2.5 maximum: 2.65 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 QFN-24-1EP_3x3mm_P0.4mm_EP1.75x1.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.invensense.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf#page=39' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 overall_height: minimum: 0.95 nominal: 1 maximum: 1.05 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.25 nominal: 0.3 maximum: 0.35 # Choosen for backwards compatibility EP_size_x: minimum: 1.65 nominal: 1.7 maximum: 1.75 EP_size_x_overwrite: 1.75 EP_size_y: minimum: 1.49 nominal: 1.54 maximum: 1.59 EP_size_y_overwrite: 1.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 6 num_pins_y: 6 chamfer_edge_pins: 0.12 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_3x4mm_P0.4mm_EP1.65x2.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_20_05-08-1742.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 4 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.2 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 # Chosen for backwards compatibility EP_size_x: nominal: 1.65 tolerance: 0.1 EP_size_y: nominal: 2.65 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 5 num_pins_y: 7 #chamfer_edge_pins: 0.12 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_4x4mm_P0.5mm_EP2.15x2.15mm: device_type: 'QFN' size_source: 'https://www.st.com/resource/en/datasheet/led1642gw.pdf#page=34' ipc_class: 'qfn' body_size_x: minimum: 3.85 nominal: 4.00 maximum: 4.15 body_size_y: minimum: 3.85 nominal: 4.00 maximum: 4.15 overall_height: minimum: 0.80 nominal: 0.90 maximum: 1.00 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 2.00 nominal: 2.15 maximum: 2.25 EP_size_y: minimum: 2.00 nominal: 2.15 maximum: 2.25 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.3 paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 QFN-24-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=278' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 # size choosen for backwards compatibility EP_size_x: minimum: 2.4 nominal: 2.5 maximum: 2.6 EP_size_x_overwrite: 2.6 EP_size_y: minimum: 2.4 nominal: 2.5 maximum: 2.6 EP_size_y_overwrite: 2.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_4x4mm_P0.5mm_EP2.65x2.65mm: device_type: 'QFN' size_source: 'http://www.cypress.com/file/46236/download' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: nominal: 4 tolerance: 0.1 body_size_y: nominal: 4 tolerance: 0.1 lead_width: nominal: 0.25 tolerance: 0.07 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: 2.65 EP_size_y: 2.65 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 QFN-24-1EP_4x4mm_P0.5mm_EP2.7x2.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 nominal: 4 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4 maximum: 4.1 overall_height: minimum: 0.85 nominal: 0.9 maximum: 0.95 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.35 maximum: 0.4 EP_size_x: minimum: 2.65 nominal: 2.7 maximum: 2.75 EP_size_y: minimum: 2.55 nominal: 2.6 maximum: 2.65 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_4x4mm_P0.5mm_EP2.7x2.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.alfarzpp.lv/eng/sc/AS3330.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0.1 body_size_y: nominal: 4 tolerance: 0.1 overall_height: nominal: 0.9 tolerance: 0.1 lead_width: nominal: 0.23 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 2.7 tolerance: 0.1 EP_size_y: nominal: 2.7 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_4x4mm_P0.5mm_EP2.8x2.8mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/hmc431.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.3 lead_len: nominal: 0.4 EP_size_x: minimum: 2.65 maximum: 2.95 EP_size_y: minimum: 2.65 maximum: 2.95 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False # The datasheet does not give the pitch as a reference dimension. Instead, it only specifies # the range. pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_4x5mm_P0.5mm_EP2.65x3.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_24_05-08-1696.pdf' #custom_name_format: '' ipc_class: qfn #'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 4.0 tolerance: 0.1 body_size_y: nominal: 5.0 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 2.65 tolerance: 0.1 EP_size_y: nominal: 3.65 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #include_suffix_in_3dpath: 'False' QFN-24-1EP_5x5mm_P0.65mm_EP3.2x3.2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/(UH24)%20QFN%2005-08-1747%20Rev%20A.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 5 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.3 tolerance: 0.05 lead_len: nominal: 0.55 tolerance: 0.1 EP_size_x: nominal: 3.2 tolerance: 0.1 EP_size_y: nominal: 3.2 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.75 grid: [1.1, 1.1] # bottom_pad_size: paste_avoid_via: True pitch: 0.65 num_pins_x: 6 num_pins_y: 6 chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_5x5mm_P0.65mm_EP3.4x3.4mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.thatcorp.com/datashts/THAT_5173_Datasheet.pdf#page=17' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 5 tolerance: 0.1 overall_height: nominal: 0.9 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.05 EP_size_x: nominal: 3.4 tolerance: 0.05 EP_size_y: nominal: 3.4 tolerance: 0.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-24-1EP_5x5mm_P0.65mm_EP3.6x3.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.nxp.com/docs/en/package-information/98ASA00734D.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 3.45 maximum: 3.75 EP_size_y: minimum: 3.45 maximum: 3.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.75 grid: [0.85, 0.85] # bottom_pad_size: paste_avoid_via: True pitch: 0.65 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-28.yaml ================================================ QFN-28-1EP_3x6mm_P0.5mm_EP1.7x4.75mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/05081926_0_UDE28.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 6 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 1.7 tolerance: 0.1 EP_size_y: nominal: 4.75 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 4] thermal_vias: count: [2, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_4x4mm_P0.4mm_EP2.3x2.3mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.issi.com/WW/pdf/31FL3731.pdf#page=21' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.95 nominal: 4 maximum: 4.05 body_size_y: minimum: 3.95 nominal: 4 maximum: 4.05 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.15 nominal: 2.3 maximum: 2.4 EP_size_y: minimum: 2.15 nominal: 2.3 maximum: 2.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 # grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_4x4mm_P0.4mm_EP2.4x2.4mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=280' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.17 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.5 nominal: 2.6 maximum: 2.7 EP_size_x_overwrite: 2.4 EP_size_y: minimum: 2.5 nominal: 2.6 maximum: 2.7 EP_size_y_overwrite: 2.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 # grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_4x4mm_P0.4mm_EP2.6x2.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'package code T2844-1; https://pdfserv.maximintegrated.com/package_dwgs/21-0139.PDF' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 nominal: 4 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4 maximum: 4.1 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.5 nominal: 2.6 maximum: 2.7 EP_size_y: minimum: 2.5 nominal: 2.6 maximum: 2.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 # grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_4x4mm_P0.45mm_EP2.4x2.4mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/8008S.pdf#page=16' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.95 nominal: 4 maximum: 4.05 body_size_y: minimum: 3.95 nominal: 4 maximum: 4.05 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 2.35 nominal: 2.4 maximum: 2.45 EP_size_y: minimum: 2.35 nominal: 2.4 maximum: 2.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 # grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.45 num_pins_x: 7 num_pins_y: 7 chamfer_edge_pins: 0.1 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28_4x4mm_P0.5mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.st.com/resource/en/datasheet/stm32f031k6.pdf#page=90' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 nominal: 4.0 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4.0 maximum: 4.1 overall_height: minimum: 0.5 nominal: 0.55 maximum: 0.6 lead_width: minimum: 0.17 maximum: 0.25 lead_len: minimum: 0.3 maximum: 0.5 pitch: 0.5 num_pins_x: 7 num_pins_y: 7 edge_heel_reduction: 0.12 chamfer_edge_pins: 0.16 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_4x5mm_P0.5mm_EP2.65x3.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/technical-documentation/data-sheets/3555fe.pdf#page=32' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0.1 body_size_y: nominal: 5 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 2.65 tolerance: 0.1 EP_size_y: nominal: 3.65 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 # EP_paste_coverage: 0.75 # grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_5x5mm_P0.5mm_EP3.35x3.35mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=283' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x: minimum: 3.15 nominal: 3.25 maximum: 3.35 EP_size_x_overwrite: 3.35 EP_size_y: minimum: 3.15 nominal: 3.25 maximum: 3.35 EP_size_y_overwrite: 3.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_5x6mm_P0.5mm_EP3.65x4.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/05081932_0_UHE28.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 6 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 3.65 tolerance: 0.1 EP_size_y: nominal: 4.65 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 4] thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_6x6mm_P0.65mm_EP4.25x4.25mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=289' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 6 tolerance: 0 body_size_y: nominal: 6 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.23 maximum: 0.35 lead_len: minimum: 0.5 maximum: 0.7 EP_size_x: minimum: 3.65 nominal: 3.7 maximum: 4.2 EP_size_x_overwrite: 4.25 EP_size_y: minimum: 3.65 nominal: 3.7 maximum: 4.2 EP_size_y_overwrite: 4.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [0.95, 0.95] # bottom_pad_size: # paste_avoid_via: False pitch: 0.65 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-28-1EP_6x6mm_P0.65mm_EP4.8x4.8mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.semtech.com/uploads/documents/sx1272.pdf#page=125' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 5.9 nominal: 6 maximum: 6.1 body_size_y: minimum: 5.9 nominal: 6 maximum: 6.1 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.35 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 4.65 nominal: 4.8 maximum: 4.9 EP_size_y: minimum: 4.65 nominal: 4.8 maximum: 4.9 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [0.95, 0.95] # bottom_pad_size: # paste_avoid_via: False pitch: 0.65 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-3x.yaml ================================================ QFN-32-1EP_4x4mm_P0.4mm_EP2.65x2.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.renesas.com/eu/en/package-image/pdf/outdrawing/l32.4x4a.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0.05 body_size_y: nominal: 4 tolerance: 0.05 overall_height: nominal: 0.9 tolerance: 0.1 lead_width: nominal: 0.2 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.05 EP_size_x: nominal: 2.65 tolerance: 0.05 EP_size_y: nominal: 2.65 tolerance: 0.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.75 grid: [0.85, 0.85] # bottom_pad_size: paste_avoid_via: True pitch: 0.4 num_pins_x: 8 num_pins_y: 8 chamfer_edge_pins: 0.1 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_4x4mm_P0.4mm_EP2.9x2.9mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/atmel-8153-8-and-16-bit-avr-microcontroller-xmega-e-atxmega8e5-atxmega16e5-atxmega32e5_datasheet.pdf#page=70' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0 body_size_y: nominal: 4 tolerance: 0 overall_height: minimum: 0.5 nominal: 0.55 maximum: 0.6 lead_width: minimum: 0.15 maximum: 0.25 lead_len: minimum: 0.3 maximum: 0.4 EP_size_x: minimum: 2.7 nominal: 2.8 maximum: 2.9 EP_size_x_overwrite: 2.9 EP_size_y: minimum: 2.7 nominal: 2.8 maximum: 2.9 EP_size_y_overwrite: 2.9 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/8008S.pdf#page=20' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 5 tolerance: 0.1 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 2.95 nominal: 3.1 maximum: 3.25 EP_size_y: minimum: 2.95 nominal: 3.1 maximum: 3.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_5x5mm_P0.5mm_EP3.3x3.3mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/00002164B.pdf#page=68' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 4.9 nominal: 5 maximum: 5.1 body_size_y: minimum: 4.9 nominal: 5 maximum: 5.1 overall_height: minimum: 0.7 nominal: 0.85 maximum: 1 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 3.2 nominal: 3.3 maximum: 3.4 EP_size_y: minimum: 3.2 nominal: 3.3 maximum: 3.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_5x5mm_P0.5mm_EP3.45x3.45mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_32_05-08-1693.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 5 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 3.45 tolerance: 0.1 EP_size_y: nominal: 3.45 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_5x5mm_P0.5mm_EP3.6x3.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://infocenter.nordicsemi.com/pdf/nRF52810_PS_v1.1.pdf#page=468' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 3.4 nominal: 3.5 maximum: 3.6 EP_size_x_overwrite: 3.6 EP_size_y: minimum: 3.4 nominal: 3.5 maximum: 3.6 EP_size_y_overwrite: 3.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_5x5mm_P0.5mm_EP3.65x3.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.exar.com/ds/mxl7704.pdf#page=35' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.28 lead_len: minimum: 0.30 nominal: 0.35 maximum: 0.40 EP_size_x: minimum: 3.55 nominal: 3.65 maximum: 3.75 EP_size_y: minimum: 3.55 nominal: 3.65 maximum: 3.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_5x5mm_P0.5mm_EP3.7x3.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.espressif.com/sites/default/files/documentation/0a-esp8285_datasheet_en.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 4.95 nominal: 5.00 maximum: 5.05 body_size_y: minimum: 4.95 nominal: 5.00 maximum: 5.05 overall_height: minimum: 0.80 nominal: 0.85 maximum: 0.90 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.35 nominal: 0.40 maximum: 0.45 EP_size_x: minimum: 3.65 nominal: 3.70 maximum: 3.75 EP_size_y: minimum: 3.65 nominal: 3.70 maximum: 3.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_7x7mm_P0.65mm_EP4.65x4.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8209-8-bit%20AVR%20ATmega16M1-32M1-64M1_Datasheet.pdf#page=426' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 7 tolerance: 0 body_size_y: nominal: 7 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.37 lead_len: minimum: 0.5 nominal: 0.6 maximum: 0.7 EP_size_x: minimum: 4.4 nominal: 4.5 maximum: 4.6 EP_size_x_overwrite: 4.65 EP_size_y: minimum: 4.4 nominal: 4.5 maximum: 4.6 EP_size_y_overwrite: 4.65 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1.05, 1.05] # bottom_pad_size: # paste_avoid_via: False pitch: 0.65 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_7x7mm_P0.65mm_EP4.7x4.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.nxp.com/docs/en/data-sheet/LPC111X.pdf#page=108' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.9 nominal: 7 maximum: 7.1 body_size_y: minimum: 6.9 nominal: 7 maximum: 7.1 overall_height: minimum: 0.8 nominal: 0.85 maximum: 1 lead_width: minimum: 0.23 nominal: 0.28 maximum: 0.35 lead_len: minimum: 0.45 nominal: 0.6 maximum: 0.75 EP_size_x: minimum: 4.55 nominal: 4.7 maximum: 4.85 EP_size_y: minimum: 4.55 nominal: 4.7 maximum: 4.85 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1.05, 1.05] # bottom_pad_size: # paste_avoid_via: False pitch: 0.65 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-32-1EP_7x7mm_P0.65mm_EP5.4x5.4mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.thatcorp.com/datashts/THAT_5171_Datasheet.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.9 maximum: 7.1 body_size_y: minimum: 6.9 maximum: 7.1 overall_height: minimum: 0.85 maximum: 0.95 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x: minimum: 5.35 maximum: 5.45 EP_size_y: minimum: 5.35 maximum: 5.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.7 grid: [1.4, 1.4] # bottom_pad_size: # paste_avoid_via: False pitch: 0.65 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-36-1EP_5x6mm_P0.5mm_EP3.6x4.1mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2100_datasheet_Rev1.08.pdf#page=43' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 4.9 nominal: 5 maximum: 5.1 body_size_y: minimum: 5.9 nominal: 6 maximum: 6.1 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 3.5 nominal: 3.6 maximum: 3.7 EP_size_y: minimum: 4.0 nominal: 4.1 maximum: 4.2 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-36-1EP_5x6mm_P0.5mm_EP3.6x4.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/(UHE36)%20QFN%2005-08-1876%20Rev%20%C3%98.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 6 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 3.6 tolerance: 0.1 EP_size_y: nominal: 4.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 4] # heel_reduction: 0.05 thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-36-1EP_6x6mm_P0.5mm_EP3.7x3.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/36L_QFN_6x6_with_3_7x3_7_EP_Punch_Dimpled_4E_C04-0241A.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 6 tolerance: 0 body_size_y: nominal: 6 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 3.6 nominal: 3.7 maximum: 3.8 EP_size_y: minimum: 3.6 nominal: 3.7 maximum: 3.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 9 num_pins_y: 9 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-36-1EP_6x6mm_P0.5mm_EP4.1x4.1mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'www.st.com/resource/en/datasheet/stm32f101t6.pdf#page=72' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 5.875 nominal: 6 maximum: 6.125 body_size_y: minimum: 5.875 nominal: 6 maximum: 6.125 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.3 lead_len: minimum: 0.35 nominal: 0.55 maximum: 0.75 EP_size_x: minimum: 1.75 nominal: 3.7 maximum: 4.25 EP_size_x_overwrite: 4.1 EP_size_y: minimum: 1.75 nominal: 3.7 maximum: 4.25 EP_size_y_overwrite: 4.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.75 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 9 num_pins_y: 9 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-38-1EP_4x6mm_P0.4mm_EP2.65x4.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_38_05-08-1750.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 tolerance: 0.1 body_size_y: nominal: 6 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.2 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 2.65 tolerance: 0.1 EP_size_y: nominal: 4.65 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 4] thermal_vias: count: [2, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 7 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-38-1EP_5x7mm_P0.5mm_EP3.15x5.15mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_38_05-08-1701.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 7 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 3.15 tolerance: 0.1 EP_size_y: nominal: 5.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 5] # heel_reduction: 0.05 thermal_vias: count: [3, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 4] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 7 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-4x.yaml ================================================ QFN-40-1EP_5x5mm_P0.4mm_EP3.6x3.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=297' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.17 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: nominal: 3.6 tolerance: 0 EP_size_y: nominal: 3.6 tolerance: 0 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.1 #deprecated thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.4 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-40-1EP_5x5mm_P0.4mm_EP3.8x3.8mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.issi.com/WW/pdf/31FL3736.pdf#page=28' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 4.9 nominal: 5 maximum: 5.1 body_size_y: minimum: 4.9 nominal: 5 maximum: 5.1 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 3.15 maximum: 3.8 EP_size_x_overwrite: 3.8 EP_size_y: minimum: 3.15 maximum: 3.8 EP_size_y_overwrite: 3.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.1 #deprecated thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.4 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-40-1EP_6x6mm_P0.5mm_EP4.6x4.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=295' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 6 tolerance: 0 body_size_y: nominal: 6 tolerance: 0 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 4.5 nominal: 4.65 maximum: 4.8 EP_size_x_overwrite: 4.6 EP_size_y: minimum: 4.5 nominal: 4.65 maximum: 4.8 EP_size_y_overwrite: 4.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.1 #deprecated thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-42-1EP_5x6mm_P0.4mm_EP3.7x4.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/05081875_0_UHE42.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0.1 body_size_y: nominal: 6 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 3.7 tolerance: 0.1 EP_size_y: nominal: 4.7 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 4] # heel_reduction: 0.05 #deprecated thermal_vias: count: [4, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.4 num_pins_x: 9 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-44-1EP_7x7mm_P0.5mm_EP5.2x5.2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/2512S.pdf#page=17' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.9 nominal: 7 maximum: 7.1 body_size_y: minimum: 6.9 nominal: 7 maximum: 7.1 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.3 lead_len: minimum: 0.59 nominal: 0.64 maximum: 0.69 EP_size_x: minimum: 5.0 nominal: 5.2 maximum: 5.4 EP_size_y: minimum: 5.0 nominal: 5.2 maximum: 5.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 #deprecated thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 11 num_pins_y: 11 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-44-1EP_7x7mm_P0.5mm_EP5.15x5.15mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_44_05-08-1763.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 7 tolerance: 0.1 body_size_y: nominal: 7 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 5.15 tolerance: 0.1 EP_size_y: nominal: 5.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 #deprecated thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 11 num_pins_y: 11 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-44-1EP_8x8mm_P0.65mm_EP6.45x6.45mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/39935c.pdf#page=152' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 8 tolerance: 0 body_size_y: nominal: 8 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.38 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 6.3 nominal: 6.45 maximum: 6.8 EP_size_y: minimum: 6.3 nominal: 6.45 maximum: 6.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 5] # heel_reduction: 0.05 #deprecated thermal_vias: count: [6, 6] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.65 num_pins_x: 11 num_pins_y: 11 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_5x5mm_P0.35mm_EP3.7x3.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf#page=47' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 4.95 nominal: 5 maximum: 5.05 body_size_y: minimum: 4.95 nominal: 5 maximum: 5.05 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.13 nominal: 0.18 maximum: 0.23 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 3.65 nominal: 3.7 maximum: 3.75 EP_size_y: minimum: 3.65 nominal: 3.7 maximum: 3.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.1 #deprecated thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.35 num_pins_x: 10 num_pins_y: 14 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_6x6mm_P0.4mm_EP4.2x4.2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://static.dev.sifive.com/SiFive-FE310-G000-datasheet-v1p5.pdf#page=20' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 6 tolerance: 0.1 body_size_y: nominal: 6 tolerance: 0.1 overall_height: nominal: 0.85 tolerance: 0.08 lead_width: nominal: 0.2 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.05 EP_size_x: nominal: 4.2 tolerance: 0.1 EP_size_y: nominal: 4.2 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.1 #deprecated thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.6 grid: [1.05, 1.05] # bottom_pad_size: paste_avoid_via: True pitch: 0.4 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_6x6mm_P0.5mm_EP4.3x4.3mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf#page=38' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 5.95 nominal: 6 maximum: 6.05 body_size_y: minimum: 5.95 nominal: 6 maximum: 6.05 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 4.25 nominal: 4.3 maximum: 4.35 EP_size_y: minimum: 4.25 nominal: 4.3 maximum: 4.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.1 #deprecated thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.4 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_6x6mm_P0.4mm_EP4.6x4.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.3.pdf#page=67' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 6 tolerance: 0 body_size_y: nominal: 6 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 4.5 nominal: 4.6 maximum: 4.7 EP_size_y: minimum: 4.5 nominal: 4.6 maximum: 4.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 #deprecated thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.6 grid: [1.2, 1.2] # bottom_pad_size: paste_avoid_via: True pitch: 0.4 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_6x6mm_P0.4mm_EP4.66x4.66mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.onsemi.com/pub/Collateral/485BA.PDF' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 6 tolerance: 0 body_size_y: nominal: 6 tolerance: 0 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.15 maximum: 0.25 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 4.4 maximum: 4.6 EP_size_x_overwrite: 4.66 EP_size_y: minimum: 4.4 maximum: 4.6 EP_size_y_overwrite: 4.66 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 #deprecated thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 # EP_paste_coverage: 0.6 grid: [1.2, 1.2] # bottom_pad_size: paste_avoid_via: True pitch: 0.4 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_7x7mm_P0.5mm_EP5.30x5.30mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2041_datasheet.pdf#page=62' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 7 tolerance: 0 body_size_y: nominal: 7 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 5.2 nominal: 5.3 maximum: 5.4 EP_size_y: minimum: 5.2 nominal: 5.3 maximum: 5.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 #deprecated thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_7x7mm_P0.5mm_EP5.45x5.45mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.thatcorp.com/datashts/THAT_626x_Datasheet.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.9 maximum: 7.1 body_size_y: minimum: 6.9 maximum: 7.1 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x: minimum: 5.31 maximum: 5.6 EP_size_x_overwrite: 5.45 EP_size_y: minimum: 5.31 maximum: 5.6 EP_size_y_overwrite: 5.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 #deprecated thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_7x7mm_P0.5mm_EP5.6x5.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.st.com/resource/en/datasheet/stm32f042k6.pdf#page=94' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.9 nominal: 7 maximum: 7.1 body_size_y: minimum: 6.9 nominal: 7 maximum: 7.1 overall_height: minimum: 0.5 nominal: 0.55 maximum: 0.6 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 5.5 nominal: 5.6 maximum: 5.7 EP_size_y: minimum: 5.5 nominal: 5.6 maximum: 5.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 #deprecated thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_7x7mm_P0.5mm_EP5.15x5.15mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_48_05-08-1704.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 7 tolerance: 0.1 body_size_y: nominal: 7 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 5.15 tolerance: 0.1 EP_size_y: nominal: 5.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] # heel_reduction: 0.05 #deprecated thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-48-1EP_8x8mm_P0.5mm_EP6.2x6.2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232H.pdf#page=49' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 8 tolerance: 0 body_size_y: nominal: 8 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.5 nominal: 0.55 maximum: 0.6 EP_size_x: minimum: 6.15 nominal: 6.2 maximum: 6.25 EP_size_y: minimum: 6.15 nominal: 6.2 maximum: 6.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 5] # heel_reduction: 0.05 #deprecated thermal_vias: count: [6, 6] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-5x.yaml ================================================ QFN-52-1EP_7x8mm_P0.5mm_EP5.41x6.45mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-qfn/QFN_52_05-08-1729.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 7 tolerance: 0.1 body_size_y: nominal: 8 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 5.41 tolerance: 0.1 EP_size_y: nominal: 6.45 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 5] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 6] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 14 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-56-1EP_7x7mm_P0.4mm_EP5.6x5.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.cypress.com/file/416486/download#page=40' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 7 tolerance: 0.1 body_size_y: nominal: 7 tolerance: 0.1 overall_height: nominal: 0.55 tolerance: 0.05 lead_width: nominal: 0.2 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 5.6 tolerance: 0.1 EP_size_y: nominal: 5.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.4 num_pins_x: 14 num_pins_y: 14 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-56-1EP_8x8mm_P0.5mm_EP4.3x4.3mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/00002142A.pdf#page=40' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 7.85 nominal: 8.00 maximum: 8.15 body_size_y: minimum: 7.85 nominal: 8.00 maximum: 8.15 overall_height: minimum: 0.70 nominal: 0.85 maximum: 1.00 lead_width: minimum: 0.15 #according to Note 2 on page 40 (table min. value is 0.18 mm) nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 4.20 nominal: 4.30 maximum: 4.40 EP_size_y: minimum: 4.20 nominal: 4.30 maximum: 4.40 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 14 num_pins_y: 14 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-56-1EP_8x8mm_P0.5mm_EP4.5x5.2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/an/scea032/scea032.pdf#page=4' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 7.85 maximum: 8.15 body_size_y: minimum: 7.85 maximum: 8.15 overall_height: minimum: 0.8 maximum: 0.9 lead_width: nominal: 0.23 tolerance: [-0.05, 0.07] lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 4.35 maximum: 4.65 EP_size_y: minimum: 5.05 maximum: 5.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 14 num_pins_y: 14 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-56-1EP_8x8mm_P0.5mm_EP5.6x5.6mm: # also known as Texas RTQ (S-PVQFN-N56) device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/tlc5957.pdf#page=23' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 7.85 maximum: 8.15 body_size_y: minimum: 7.85 maximum: 8.15 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.18 maximum: 0.30 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 5.6 tolerance: 0.1 EP_size_y: nominal: 5.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 14 num_pins_y: 14 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-56-1EP_8x8mm_P0.5mm_EP5.9x5.9mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/00001734B.pdf#page=50' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 7.85 nominal: 8.00 maximum: 8.15 body_size_y: minimum: 7.85 nominal: 8.00 maximum: 8.15 overall_height: minimum: 0.70 nominal: 0.85 maximum: 1.00 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: nominal: 5.9 tolerance: 0.1 EP_size_y: nominal: 5.9 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 14 num_pins_y: 14 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-64_9x9.yaml ================================================ QFN-64-1EP_9x9mm_P0.5mm_EP3.8x3.8xmm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://datasheet.lcsc.com/szlcsc/Realtek-Semicon-RTL8211EG-VB-CG_C69264.pdf#page=77' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: 9.0 body_size_y: 9.0 lead_width: 0.18 .. 0.25 .. 0.30 lead_len: 0.30 .. 0.40 .. 0.50 EP_size_x: 3.55 .. 3.80 .. 4.05 EP_size_y: 3.55 .. 3.80 .. 4.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP4.7x4.7mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/60001477A.pdf (page 1083)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: #body_size_x_min: 8.9 body_size_x: 9.0 #body_size_x_max: 9.1 #body_size_y_min: 8.9 body_size_y: 9.0 #body_size_y_max: 9.1 lead_width_min: 0.15 lead_width_max: 0.25 lead_len_min: 0.3 lead_len_max: 0.55 EP_size_x_min: 4.6 EP_size_x: 4.7 EP_size_x_max: 4.8 EP_size_y_min: 4.6 EP_size_y: 4.7 EP_size_y_max: 4.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP5.4x5.4mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/70593d.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: #body_size_x_min: 8.9 body_size_x: 9.0 #body_size_x_max: 9.1 #body_size_y_min: 8.9 body_size_y: 9.0 #body_size_y_max: 9.1 lead_width_min: 0.2 lead_width_max: 0.3 lead_len_min: 0.3 lead_len_max: 0.5 EP_size_x_min: 5.3 EP_size_x: 5.4 EP_size_x_max: 5.5 EP_size_y_min: 5.3 EP_size_y: 5.4 EP_size_y_max: 5.5 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.65 #grid: [0.98, 0.98] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP6x6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/tusb8041.pdf#page=42' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x_min: 8.9 body_size_x: 9.0 body_size_x_max: 9.1 body_size_y_min: 8.9 body_size_y: 9.0 body_size_y_max: 9.1 lead_width_min: 0.18 lead_width_max: 0.3 lead_len_min: 0.3 lead_len_max: 0.5 EP_size_x_min: 5.95 EP_size_x: 6 EP_size_x_max: 6.05 EP_size_y_min: 5.95 EP_size_y: 6 EP_size_y_max: 6.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 # EP_paste_coverage: 0.65 # grid: [0.8, 0.8] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP7.15x7.15mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.analog.com/media/en/technical-documentation/data-sheets/229321fa.pdf#page=27' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 9.0 tolerance: 0.1 body_size_y: nominal: 9.0 tolerance: 0.1 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 7.15 tolerance: 0.1 EP_size_y: nominal: 7.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 5] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [6, 6] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP7.3x7.3mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/00002304A.pdf (page 43)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x_min: 8.9 body_size_x: 9.0 body_size_x_max: 9.1 body_size_y_min: 8.9 body_size_y: 9.0 body_size_y_max: 9.1 lead_width_min: 0.18 lead_width_max: 0.3 lead_len_min: 0.3 lead_len_max: 0.5 EP_size_x_min: 7.2 EP_size_x: 7.3 EP_size_x_max: 7.4 EP_size_y_min: 7.2 EP_size_y: 7.3 EP_size_y_max: 7.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 5] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [6, 6] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP7.5x7.5mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/doc7593.pdf (page 432)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: #body_size_x_min: 8.9 body_size_x: 9.0 #body_size_x_max: 9.1 #body_size_y_min: 8.9 body_size_y: 9.0 #body_size_y_max: 9.1 lead_width_min: 0.18 lead_width_max: 0.3 lead_len_min: 0.3 lead_len_max: 0.55 EP_size_x_min: 7.4 EP_size_x: 7.5 EP_size_x_max: 7.6 EP_size_y_min: 7.4 EP_size_y: 7.5 EP_size_y_max: 7.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [6, 6] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [7, 7] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 chamfer_edge_pins: 0.1 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP7.65x7.65mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf (page 415)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x_min: 8.9 body_size_x: 9.0 body_size_x_max: 9.1 body_size_y_min: 8.9 body_size_y: 9.0 body_size_y_max: 9.1 lead_width_min: 0.18 lead_width_max: 0.3 lead_len_min: 0.35 lead_len_max: 0.45 EP_size_x_min: 7.5 EP_size_x: 7.65 EP_size_x_max: 7.8 EP_size_y_min: 7.5 EP_size_y: 7.65 EP_size_y_max: 7.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [6, 6] # heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [7, 7] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 # EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-6x.yaml ================================================ QFN-64-1EP_8x8mm_P0.4mm_EP6.5x6.5mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/64L_VQFN_8x8_with%206_5x6_5%20EP_JXX_C04-0437A.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 8 tolerance: 0 body_size_y: nominal: 8 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 6.4 nominal: 6.5 maximum: 6.6 EP_size_y: minimum: 6.4 nominal: 6.5 maximum: 6.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [5, 5] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [6, 6] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.4 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP4.35x4.35mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT2232H.pdf#page=57' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: nominal: 9 body_size_y: nominal: 9 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 4.3 nominal: 4.35 maximum: 4.4 EP_size_y: minimum: 4.3 nominal: 4.35 maximum: 4.4 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP5.2x5.2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.silabs.com/documents/public/data-sheets/Si5345-44-42-D-DataSheet.pdf#page=51' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: nominal: 9 tolerance: 0 body_size_y: nominal: 9 tolerance: 0 overall_height: maximum: 0.9 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 5.10 nominal: 5.20 maximum: 5.30 EP_size_y: minimum: 5.10 nominal: 5.20 maximum: 5.30 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-64-1EP_9x9mm_P0.5mm_EP5.45x5.45mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.infineon.com/dgdl/Infineon-MA12040-DS-v01_00-EN.pdf?fileId=5546d46264a8de7e0164b7467a3d617c#page=81' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: nominal: 9 tolerance: 0.1 body_size_y: nominal: 9 tolerance: 0.1 overall_height: maximum: 0.9 lead_width: minimum: 0.15 nominal: 0.25 maximum: 0.35 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 5.35 nominal: 5.45 maximum: 5.55 EP_size_y: minimum: 5.35 nominal: 5.45 maximum: 5.55 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' QFN-68-1EP_8x8mm_P0.4mm_EP5.2x5.2mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://cdn.microsemi.com/documents/1bf6886f-5919-4508-a50b-b1dbf3fdf0f4/download/#page=98' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 8 tolerance: 0 body_size_y: nominal: 8 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 0.9 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 5.1 nominal: 5.2 maximum: 5.3 EP_size_y: minimum: 5.1 nominal: 5.2 maximum: 5.3 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.4 num_pins_x: 17 num_pins_y: 17 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-7x.yaml ================================================ QFN-72-1EP_10x10mm_P0.5mm_EP6x6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/00001682C.pdf#page=70' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 9.9 nominal: 10.0 maximum: 10.1 body_size_y: minimum: 9.9 nominal: 10.0 maximum: 10.1 overall_height: minimum: 0.8 nominal: 0.85 maximum: 1.0 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 5.9 nominal: 6.0 maximum: 6.1 EP_size_y: minimum: 5.9 nominal: 6.0 maximum: 6.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.1 #deprecated thermal_vias: count: [6, 6] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [5, 5] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 18 num_pins_y: 18 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-mini-circuits.yaml ================================================ QFN-12-1EP_3x3mm_P0.51mm_EP1.45x1.45mm: device_type: 'QFN' size_source: 'https://ww2.minicircuits.com/case_style/DQ1225.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 3 tolerance: 0.1016 body_size_y: nominal: 3 tolerance: 0.1016 overall_height: nominal: 0.89 tolerance: 0.1016 lead_width: nominal: 0.23 tolerance: 0.1016 lead_len: nominal: 0.41 tolerance: 0.1016 EP_size_x: nominal: 1.45 tolerance: 0.1016 EP_size_y: nominal: 1.45 tolerance: 0.1016 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.51 num_pins_x: 3 num_pins_y: 3 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-onsemi-vct.yml ================================================ OnSemi_VCT-28_3.5x3.5mm_P0.4mm: device_type: 'VCT' manufacturer: 'OnSemi' #part_number: 'mpn' size_source: 'http://www.onsemi.com/pub/Collateral/601AE.PDF' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3.5 tolerance: 0.08 body_size_y: nominal: 3.5 tolerance: 0.08 lead_width: minimum: .14 maximum: .24 lead_len: minimum: .35 maximum: .45 pitch: 0.4 num_pins_x: 7 num_pins_y: 7 chamfer_edge_pins: 0.09 edge_heel_reduction: 0.1 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn-other-pincounts.yaml ================================================ QFN-76-1EP_9x9mm_P0.4mm_EP3.8x3.8mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.marvell.com/documents/bqcwxsoiqfjkcjdjhkvc/#page=19' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 9 tolerance: 0 body_size_y: nominal: 9 tolerance: 0 overall_height: minimum: 0.8 nominal: 0.85 maximum: 1 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 3.8 tolerance: 0.2 EP_size_y: nominal: 3.8 tolerance: 0.2 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] #heel_reduction: 0.1 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.6 grid: [1.2, 1.2] # bottom_pad_size: paste_avoid_via: True pitch: 0.4 num_pins_x: 19 num_pins_y: 19 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/qfn_texas.yaml ================================================ Texas_RUM0016A: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/lmh0074.pdf#page=13' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_RUM00{pincount}A_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: nominal: 4 tolerance: 0.1 body_size_y: nominal: 4 tolerance: 0.1 overall_height: maximum: 0.8 lead_width: nominal: 0.3 tolerance: 0.05 lead_len: nominal: 0.4 tolerance: 0.1 EP_size_x: nominal: 2.6 tolerance: 0.1 EP_size_y: nominal: 2.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.7 # grid: # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N16_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430g2001.pdf#page=43' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.23 maximum: 0.38 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.7 tolerance: 0.1 EP_size_y: nominal: 2.7 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.5 # grid: # bottom_pad_size: # paste_avoid_via: True pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PWQFN-N16_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/drv8801.pdf#page=31 MO-220 variation VGGC' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PWQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.85 maximum: 4.15 body_size_y: minimum: 3.85 maximum: 4.15 overall_height: minimum: 0.7 maximum: 0.8 lead_width: minimum: 0.23 maximum: 0.38 lead_len: minimum: 0.45 maximum: 0.65 EP_size_x: nominal: 2.1 tolerance: 0.1 EP_size_y: nominal: 2.1 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.7 # grid: # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N20_EP2.4x2.4: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/cc1101.pdf#page=101' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.85 maximum: 4.15 body_size_y: minimum: 3.85 maximum: 4.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.30 lead_len: minimum: 0.45 maximum: 0.65 EP_size_x: nominal: 2.4 tolerance: 0.1 EP_size_y: nominal: 2.4 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.5 # grid: # bottom_pad_size: # paste_avoid_via: True pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N20_EP2.7x2.7: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/drv8662.pdf#page=23' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.85 maximum: 4.15 body_size_y: minimum: 3.85 maximum: 4.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.30 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.7 tolerance: 0.1 EP_size_y: nominal: 2.7 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.7 # grid: # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N20_EP3.15x3.15: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'www.ti.com/lit/ds/symlink/tps7a7200.pdf#page=36' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 4.85 maximum: 5.15 body_size_y: minimum: 4.85 maximum: 5.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.23 maximum: 0.38 lead_len: minimum: 0.45 maximum: 0.65 EP_size_x: nominal: 3.15 tolerance: 0.1 EP_size_y: nominal: 3.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 paste_between_vias: 1 paste_rings_outside: 1 # EP_num_paste_pads: [2, 2] # EP_paste_coverage: 0.7 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: False pitch: 0.65 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PWQFN-N24_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/bq25601.pdf#page=54' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PWQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.85 maximum: 4.15 body_size_y: minimum: 3.85 maximum: 4.15 overall_height: minimum: 0.7 maximum: 0.8 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.7 tolerance: 0.1 EP_size_y: nominal: 2.7 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.7 # grid: # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N24_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430fr5720.pdf#page=108' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.1 tolerance: 0.1 EP_size_y: nominal: 2.1 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.05 EP_paste_coverage: 0.7 # paste_between_vias: 1 # paste_rings_outside: 1 # EP_num_paste_pads: [2, 2] # EP_paste_coverage: 0.5 # grid: # bottom_pad_size: paste_avoid_via: False Texas_R-PWQFN-N28_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/tps51363.pdf#page=29' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_R-PWQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.4 maximum: 3.6 body_size_y: minimum: 4.4 maximum: 4.6 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.15 maximum: 0.25 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.1 tolerance: 0.1 EP_size_y: nominal: 3.1 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.4 num_pins_x: 5 num_pins_y: 9 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.05 EP_paste_coverage: 0.7 # paste_between_vias: 1 # paste_rings_outside: 1 # EP_num_paste_pads: [2, 2] # EP_paste_coverage: 0.5 # grid: # bottom_pad_size: paste_avoid_via: False Texas_S-PWQFN-N32_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.ti.com/lit/ds/symlink/bq25703a.pdf#page=90' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PWQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.85 maximum: 4.15 body_size_y: minimum: 3.85 maximum: 4.15 overall_height: minimum: 0.7 maximum: 0.8 lead_width: minimum: 0.15 maximum: 0.25 lead_len: minimum: 0.25 maximum: 0.45 EP_size_x: nominal: 2.8 tolerance: 0.1 EP_size_y: nominal: 2.8 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.4 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.05 EP_paste_coverage: 0.7 # paste_between_vias: 1 # paste_rings_outside: 1 # EP_num_paste_pads: [2, 2] # EP_paste_coverage: 0.5 # grid: # bottom_pad_size: paste_avoid_via: False Texas_S-PVQFN-N32_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430f1122.pdf#page=54' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 4.9 maximum: 5.1 body_size_y: minimum: 4.9 maximum: 5.1 overall_height: maximum: 1.0 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 3.45 tolerance: 0.1 EP_size_y: nominal: 3.45 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [4, 4] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: True pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N36_EP: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/slvsba5d/slvsba5d.pdf#page=35' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 5.9 maximum: 6.1 body_size_y: minimum: 5.9 maximum: 6.1 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.45 maximum: 0.65 EP_size_x: nominal: 4.4 tolerance: 0.1 EP_size_y: nominal: 4.4 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [4, 4] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1.05, 1.05] # bottom_pad_size: # paste_avoid_via: True pitch: 0.5 num_pins_x: 9 num_pins_y: 9 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N40_EP2.9x2.9mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430fr5731.pdf#page=111 JEDEC MO-220 variation VJJD-2' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 5.85 maximum: 6.15 body_size_y: minimum: 5.85 maximum: 6.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: nominal: 0.23 tolerance: [-0.05, 0.07] lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.9 tolerance: 0.1 EP_size_y: nominal: 2.9 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [4, 4] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1.05, 1.05] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N40_EP3.52x2.62mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/drv8308.pdf#page=56 JEDEC MO-220 variation VJJD-2' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 5.85 maximum: 6.15 body_size_y: minimum: 5.85 maximum: 6.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: nominal: 0.23 tolerance: [-0.05, 0.07] lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 3.52 tolerance: 0.1 EP_size_y: nominal: 2.62 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 2] thermal_vias: count: [4, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [4, 4] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1.05, 1.05] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N40_EP4.15x4.15mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430g2755.pdf#page=70 JEDEC MO-220 variation VJJD-2' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 5.85 maximum: 6.15 body_size_y: minimum: 5.85 maximum: 6.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: nominal: 0.23 tolerance: [-0.05, 0.07] lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 4.15 tolerance: 0.1 EP_size_y: nominal: 4.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [4, 4] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.7 grid: [1.0, 1.0] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N40_EP4.6x4.6mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/dac7750.pdf#page=54' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 5.85 maximum: 6.15 body_size_y: minimum: 5.85 maximum: 6.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: nominal: 0.23 tolerance: [-0.05, 0.07] lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 4.6 tolerance: 0.1 EP_size_y: nominal: 4.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [4, 4] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.7 grid: [1.15, 1.15] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N48_EP: #RGZ0048A device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430f5232.pdf#page=111' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 6.9 maximum: 7.1 body_size_y: minimum: 6.9 maximum: 7.1 overall_height: maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 5.15 tolerance: 0.1 EP_size_y: nominal: 5.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [4, 4] thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [4, 4] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [1, 1] # bottom_pad_size: # paste_avoid_via: True pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_S-PVQFN-N64_EP: #RGC0064B device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430f5217.pdf#page=120' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 8.9 maximum: 9.1 body_size_y: minimum: 8.9 maximum: 9.1 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 4.25 tolerance: 0.1 EP_size_y: nominal: 4.25 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 EP_paste_coverage: 0.65 grid: [0.8, 0.8] # bottom_pad_size: # paste_avoid_via: False pitch: 0.5 num_pins_x: 16 num_pins_y: 16 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' Texas_VQFN_RGE0024H: device_type: 'QFN' manufacturer: 'Texas' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/tlc5971.pdf#page=39' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_RGE00{pincount}H_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 1.0 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.28 maximum: 0.48 EP_size_x: nominal: 2.7 tolerance: 0.1 EP_size_y: nominal: 2.7 tolerance: 0.1 EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.05 # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 EP_num_paste_pads: [2, 2] # grid: # bottom_pad_size: paste_avoid_via: False Texas_VQFN_RGE0024C: device_type: 'QFN' manufacturer: 'Texas' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/pca9548a.pdf#page=37' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_RGE00{pincount}C_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.1 tolerance: 0.1 EP_size_y: nominal: 2.1 tolerance: 0.1 EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.05 # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # grid: # bottom_pad_size: paste_avoid_via: False Texas_RGV_S-PVQFN-N16_EP2.1x2.1mm: device_type: 'QFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/ina3221.pdf#page=44' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. custom_name_format: 'Texas_RGV_S-PVQFN-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' body_size_x: minimum: 3.85 maximum: 4.15 body_size_y: minimum: 3.85 maximum: 4.15 overall_height: minimum: 0.8 maximum: 1.0 lead_width: minimum: 0.23 maximum: 0.38 lead_len: minimum: 0.45 maximum: 0.65 EP_size_x: nominal: 2.1 tolerance: 0.1 EP_size_y: nominal: 2.1 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.75 # grid: # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/special_qfn.yaml ================================================ Texas_X2QFN-12_1.6x1.6mm_P0.4mm: device_type: 'X2QFN' manufacturer: 'Texas' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ml/mpqf391c/mpqf391c.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 1.55 maximum: 1.65 body_size_y: minimum: 1.55 maximum: 1.65 overall_height: maximum: 0.4 lead_width: minimum: 0.15 maximum: 0.25 lead_len_V: minimum: 0.2 maximum: 0.4 lead_len_H: minimum: 0.4 maximum: 0.6 heel_reduction: 0.075 pitch: 0.4 num_pins_x: 4 num_pins_y: 2 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/tqfn.yaml ================================================ TQFN-16-1EP_3x3mm_P0.5mm_EP1.23x1.23mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0136.PDF (T1633-5), https://pdfserv.maximintegrated.com/land_patterns/90-0032.PDF' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 body_size_y: nominal: 3 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: 1.23 EP_size_y: 1.23 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-16-1EP_3x3mm_P0.5mm_EP1.6x1.6mm: device_type: 'TQFN' ipc_class: 'qfn' size_source: 'https://www.diodes.com/assets/Datasheets/PI6C5946002.pdf#page=12' body_size_x: minimum: 2.9 nominal: 3.0 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3.0 maximum: 3.1 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 1.6 nominal: 1.8 maximum: 1.9 EP_size_y: minimum: 1.6 nominal: 1.8 maximum: 1.9 EP_size_x_overwrite: 1.6 EP_size_y_overwrite: 1.6 EP_num_paste_pads: [2, 2] pitch: 0.5 num_pins_x: 4 num_pins_y: 4 TQFN-16-1EP_5x5mm_P0.8mm_EP2.29x2.29mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T1655-4)' #custom_name_format: 'TQFN-24-1EP_4x4mm_P0.5mm_EP2.8x2.8mm_PullBack{vias:s}' ipc_class: 'qfn' #'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 5.0 body_size_y: nominal: 5.0 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.35 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.19 nominal: 2.29 maximum: 2.39 EP_size_y: minimum: 2.19 nominal: 2.29 maximum: 2.39 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.8 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #include_suffix_in_3dpath: 'False' TQFN-16-1EP_5x5mm_P0.8mm_EP3.1x3.1mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T1655-2)' #custom_name_format: 'TQFN-24-1EP_4x4mm_P0.5mm_EP2.8x2.8mm_PullBack{vias:s}' ipc_class: 'qfn' #'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 5.0 body_size_y: nominal: 5.0 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.25 nominal: 0.3 maximum: 0.35 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 3.0 nominal: 3.1 maximum: 3.2 EP_size_y: minimum: 3.0 nominal: 3.1 maximum: 3.2 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.8 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #include_suffix_in_3dpath: 'False' TQFN-20-1EP_5x5mm_P0.65mm_EP3.1x3.1mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T2055-3)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.25 nominal: 0.30 maximum: 0.35 lead_len: minimum: 0.45 nominal: 0.55 maximum: 0.65 EP_size_x: minimum: 3.0 nominal: 3.1 maximum: 3.2 EP_size_y: minimum: 3.0 nominal: 3.1 maximum: 3.2 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-20-1EP_5x5mm_P0.65mm_EP3.25x3.25mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T2055-5)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.25 nominal: 0.30 maximum: 0.35 # The footprints with EP3.25mm have a specified lead length of 0.4mm # (while the default for 20-pins is 0.55mm). This uses the default lead # length (instead of the actual 0.4mm) for calculating the pad size, # to match the landing pattern recommended by Maxim (90-0010). lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 3.15 nominal: 3.25 maximum: 3.35 EP_size_y: minimum: 3.15 nominal: 3.25 maximum: 3.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-24-1EP_4x4mm_P0.5mm_EP2.8x2.8mm_PullBack: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://ams.com/documents/20143/36005/AS1115_DS000206_1-00.pdf' custom_name_format: 'TQFN-24-1EP_4x4mm_P0.5mm_EP2.8x2.8mm_PullBack{vias:s}' ipc_class: 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 4.0 body_size_y: nominal: 4.0 overall_height: minimum: 0.5 nominal: 0.55 maximum: 0.65 lead_to_edge: minimum: 0 maximum: 0.15 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.35 body_to_inside_lead_edge: minimum: 0.3 nominal: 0.35 maximum: 0.4 EP_size_x: minimum: 2.7 nominal: 2.8 maximum: 2.9 EP_size_y: minimum: 2.7 nominal: 2.8 maximum: 2.9 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.65 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #include_suffix_in_3dpath: 'False' TQFN-28-1EP_5x5mm_P0.50mm_EP2.70x2.70mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T2855-4)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.45 nominal: 0.55 maximum: 0.65 EP_size_x: minimum: 2.60 nominal: 2.70 maximum: 2.80 EP_size_y: minimum: 2.60 nominal: 2.70 maximum: 2.80 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.50 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-28-1EP_5x5mm_P0.50mm_EP3.25x3.25mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T2855-3)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 # There are variations of this footprint with a specified lead length # of 0.4mm (while the default for 28-pins is 0.55mm). This uses the # default lead length (instead of 0.4mm) for calculating the pad size, # to match the landing pattern recommended by Maxim for both the 0.4mm # and 0.55mm lead length variations (90-0028). lead_len: minimum: 0.45 nominal: 0.55 maximum: 0.65 EP_size_x: minimum: 3.15 nominal: 3.25 maximum: 3.35 EP_size_y: minimum: 3.15 nominal: 3.25 maximum: 3.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.50 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-32-1EP_5x5mm_P0.50mm_EP2.10x2.10mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T3255-6)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 2.00 nominal: 2.10 maximum: 2.20 EP_size_y: minimum: 2.00 nominal: 2.10 maximum: 2.20 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.50 num_pins_x: 8 num_pins_y: 8 chamfer_edge_pins: 0.09 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-32-1EP_5x5mm_P0.50mm_EP3.10x3.10mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T3255-3)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 3.00 nominal: 3.10 maximum: 3.20 EP_size_y: minimum: 3.00 nominal: 3.10 maximum: 3.20 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.50 num_pins_x: 8 num_pins_y: 8 chamfer_edge_pins: 0.09 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-32-1EP_5x5mm_P0.50mm_EP3.40x3.40mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T3255-9)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 3.30 nominal: 3.40 maximum: 3.50 EP_size_y: minimum: 3.30 nominal: 3.40 maximum: 3.50 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.50 num_pins_x: 8 num_pins_y: 8 chamfer_edge_pins: 0.09 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-40-1EP_5x5mm_P0.40mm_EP3.50x3.50mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0140.PDF (T4055-1)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.15 nominal: 0.20 maximum: 0.25 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 3.40 nominal: 3.50 maximum: 3.60 EP_size_y: minimum: 3.40 nominal: 3.50 maximum: 3.60 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.40 num_pins_x: 10 num_pins_y: 10 chamfer_edge_pins: 0.12 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' TQFN-48-1EP_7x7mm_P0.5mm_EP5.1x5.1mm: device_type: 'TQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://pdfserv.maximintegrated.com/package_dwgs/21-0144.PDF' #T4877-3 ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.9 nominal: 7 maximum: 7.1 body_size_y: minimum: 6.9 nominal: 7 maximum: 7.1 overall_height: minimum: 0.7 nominal: 0.75 maximum: 0.8 lead_width: minimum: 0.20 nominal: 0.25 maximum: 0.30 lead_len: minimum: 0.30 nominal: 0.40 maximum: 0.50 EP_size_x: minimum: 4.95 nominal: 5.1 maximum: 5.25 EP_size_y: minimum: 4.95 nominal: 5.1 maximum: 5.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/ufqfpn.yaml ================================================ UFQFPN-32-1EP_5x5mm_P0.5mm_EP3.5x3.5mm: device_type: 'UFQFPN' size_source: 'https://www.st.com/resource/en/datasheet/stm32g071k8.pdf' body_size_x: minimum: 4.9 nominal: 5 maximum: 5.1 body_size_y: minimum: 4.9 nominal: 5 maximum: 5.1 overall_height: minimum: 0.5 nominal: 0.55 maximum: 0.6 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.28 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 3.4 nominal: 3.5 maximum: 3.6 EP_size_y: minimum: 3.4 nominal: 3.5 maximum: 3.6 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 paste_via_clearance: 0.1 paste_avoid_via: False pitch: 0.50 num_pins_x: 8 num_pins_y: 8 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/uqfn.yaml ================================================ UQFN-10_1.3x1.8mm_P0.4mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/00001725D.pdf (Page 9)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 1.3 tolerance: 0 body_size_y: nominal: 1.8 tolerance: 0 lead_width: minimum: 0.15 maximum: 0.25 lead_len_V: minimum: 0.35 maximum: 0.45 lead_len_H: minimum: 0.45 maximum: 0.55 heel_reduction: 0.05 #fnecessary to reach 0.2mm clearance between vertical and horizontal pads pitch: 0.4 num_pins_x: 3 num_pins_y: 2 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-10_1.6x2.1mm_P0.5mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/00001725D.pdf (Page 12)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 1.6 tolerance: 0 body_size_y: nominal: 2.1 tolerance: 0 lead_width: minimum: 0.2 maximum: 0.3 lead_len_V: minimum: 0.35 maximum: 0.45 lead_len_H: minimum: 0.6 maximum: 0.7 # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) pitch: 0.5 num_pins_x: 3 num_pins_y: 2 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-16-1EP_4x4mm_P0.65mm_EP2.6x2.6mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/16L_UQFN_4x4x0_5mm_JQ_C04257A.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 body_size_y: nominal: 4 overall_height: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_width: minimum: 0.25 maximum: 0.35 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 2.5 maximum: 2.7 EP_size_y: minimum: 2.5 maximum: 2.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-20-1EP_3x3mm_P0.4mm_EP1.85x1.85mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=332' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 body_size_y: nominal: 3 overall_height: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_width: minimum: 0.15 nominal: 0.20 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 1.65 nominal: 1.75 maximum: 1.85 EP_size_x_overwrite: 1.85 EP_size_y: minimum: 1.65 nominal: 1.75 maximum: 1.85 EP_size_y_overwrite: 1.85 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-20-1EP_4x4mm_P0.5mm_EP2.8x2.8mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/40001839B.pdf#page=464' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 body_size_y: nominal: 4 overall_height: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_width: minimum: 0.2 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.6 nominal: 2.7 maximum: 2.8 EP_size_x_overwrite: 2.8 EP_size_y: minimum: 2.6 nominal: 2.7 maximum: 2.8 EP_size_y_overwrite: 2.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 5 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-28-1EP_4x4mm_P0.4mm_EP2.35x2.35mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=338' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 4 body_size_y: nominal: 4 overall_height: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.55 nominal: 2.65 maximum: 2.75 EP_size_x_overwrite: 2.35 EP_size_y: minimum: 2.55 nominal: 2.65 maximum: 2.75 EP_size_y_overwrite: 2.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 7 num_pins_y: 7 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-40-1EP_5x5mm_P0.4mm_EP3.8x3.8mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=345' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 body_size_y: nominal: 5 overall_height: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 3.6 nominal: 3.7 maximum: 3.8 EP_size_x_overwrite: 3.8 EP_size_y: minimum: 3.6 nominal: 3.7 maximum: 3.8 EP_size_y_overwrite: 3.8 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.7 grid: [1.3, 1.3] # bottom_pad_size: #paste_avoid_via: False pitch: 0.4 num_pins_x: 10 num_pins_y: 10 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-48-1EP_6x6mm_P0.4mm_EP4.45x4.45mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/PackagingSpec/00000049BQ.pdf#page=347' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 6 body_size_y: nominal: 6 overall_height: minimum: 0.45 nominal: 0.5 maximum: 0.55 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 4.45 nominal: 4.6 maximum: 4.75 EP_size_x_overwrite: 4.45 EP_size_y: minimum: 4.45 nominal: 4.6 maximum: 4.75 EP_size_y_overwrite: 4.45 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 1 paste_rings_outside: 1 #EP_paste_coverage: 0.7 grid: [1.4, 1.4] # bottom_pad_size: #paste_avoid_via: False pitch: 0.4 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' UQFN-48-1EP_6x6mm_P0.4mm_EP4.62x4.62mm: device_type: 'UQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://github.com/KiCad/kicad-symbols/pull/1189#issuecomment-449506354' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 5.9 nominal: 6 maximum: 6.1 body_size_y: minimum: 5.9 nominal: 6 maximum: 6.1 lead_width: minimum: 0.15 nominal: 0.2 maximum: 0.25 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x_min: 4.52 EP_size_x_max: 4.72 EP_size_y_min: 4.52 EP_size_y_max: 4.72 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [3, 3] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.6 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: True pitch: 0.4 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/vqfn.yaml ================================================ VQFN-16-1EP_3x3mm_P0.5mm_EP1.6x1.6mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/cdclvp1102.pdf#page=28' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 maximum: 3.1 body_size_y: minimum: 2.9 maximum: 3.1 overall_height: maximum: 1 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 1.6 tolerance: 0.05 EP_size_y: nominal: 1.6 tolerance: 0.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.08 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-16-1EP_3x3mm_P0.5mm_EP1.45x1.45mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/sbos354a/sbos354a.pdf, JEDEC MO-220 variant VEED-6' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 maximum: 3.1 body_size_y: minimum: 2.9 maximum: 3.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 1.45 tolerance: 0.1 EP_size_y: nominal: 1.45 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.08 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-16-1EP_3x3mm_P0.5mm_EP1.68x1.68mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/tlv62095.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 maximum: 3.1 body_size_y: minimum: 2.9 maximum: 3.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 1.68 tolerance: 0.07 EP_size_y: nominal: 1.68 tolerance: 0.07 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.08 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-16-1EP_3x3mm_P0.5mm_EP1.8x1.8mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.st.com/resource/en/datasheet/stspin220.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.85 nominal: 3 maximum: 3.15 body_size_y: minimum: 2.85 nominal: 3 maximum: 3.15 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.18 nominal: 0.25 maximum: 0.3 lead_len: minimum: 0.45 nominal: 0.5 maximum: 0.55 EP_size_x: minimum: 1.7 nominal: 1.8 maximum: 1.9 EP_size_y: minimum: 1.7 nominal: 1.8 maximum: 1.9 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] heel_reduction: 0.2 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.08 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-20-1EP_3x3mm_P0.4mm_EP1.7x1.7mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/20%20Lead%20VQFN%203x3x0_9mm_1_7EP%20U2B%20C04-21496a.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 body_size_y: nominal: 3 overall_height: minimum: 0.8 maximum: 0.9 lead_width: minimum: 0.15 maximum: 0.25 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x: 1.7 EP_size_y: 1.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 5 num_pins_y: 5 chamfer_edge_pins: 0.08 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-20-1EP_3x3mm_P0.45mm_EP1.55x1.55mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/doc8246.pdf#page=264' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.9 nominal: 3 maximum: 3.1 body_size_y: minimum: 2.9 nominal: 3 maximum: 3.1 overall_height: minimum: 0.75 nominal: 0.8 maximum: 0.85 lead_width: minimum: 0.17 maximum: 0.27 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x_min: 1.4 EP_size_x: 1.55 EP_size_x_max: 1.7 EP_size_y_min: 1.4 EP_size_y: 1.55 EP_size_y_max: 1.7 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.45 num_pins_x: 5 num_pins_y: 5 chamfer_edge_pins: 0.15 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-24-1EP_4x4mm_P0.5mm_EP2.45x2.45mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/msp430f1101a.pdf' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 3.9 nominal: 4.0 maximum: 4.1 body_size_y: minimum: 3.9 nominal: 4.0 maximum: 4.1 overall_height: maximum: 1 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: minimum: 2.35 nominal: 2.45 maximum: 2.55 EP_size_y: minimum: 2.35 nominal: 2.45 maximum: 2.55 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] heel_reduction: 0.1 #for relatively large EP pads (increase clearance) #EP_size_limit_x: 2.7 #for relatively large EP pads (increase clearance) #EP_size_limit_y: 2.7 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] EP_paste_coverage: 0.55 # grid: # bottom_pad_size: # paste_avoid_via: True pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-28-1EP_4x4mm_P0.45mm_EP2.4x2.4mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-9505-AT42-QTouch-BSW-AT42QT1060_Datasheet.pdf#page=28' ipc_class: 'qfn' #ipc_density: 'least' body_size_x: minimum: 3.95 nominal: 4 maximum: 4.05 body_size_y: minimum: 3.95 nominal: 4 maximum: 4.05 overall_height: minimum: 0.8 nominal: 0.9 maximum: 1 lead_width: minimum: 0.17 nominal: 0.22 maximum: 0.27 lead_len: minimum: 0.35 nominal: 0.4 maximum: 0.45 EP_size_x: minimum: 2.35 nominal: 2.4 maximum: 2.45 EP_size_y: minimum: 2.35 nominal: 2.4 maximum: 2.45 EP_num_paste_pads: [2, 2] thermal_vias: count: [3,3] drill: 0.3 paste_via_clearance: 0.1 paste_avoid_via: False EP_paste_coverage: 0.7 pitch: 0.45 num_pins_x: 7 num_pins_y: 7 VQFN-28-1EP_4x5mm_P0.5mm_EP2.55x3.55mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/lm5175.pdf#page=40' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 4.9 maximum: 5.1 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.55 tolerance: 0.1 EP_size_y: nominal: 3.55 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 # EP_paste_coverage: 0.75 # grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-32-1EP_5x5mm_P0.5mm_EP3.1x3.1mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/devicedoc/atmel-9520-at42-qtouch-bsw-at42qt1110_datasheet.pdf#page=42' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 4.9 nominal: 5 maximum: 5.1 body_size_y: minimum: 4.9 nominal: 5 maximum: 5.1 overall_height: minimum: 0.8 nominal: 0.85 maximum: 1 lead_width: minimum: 0.18 nominal: 0.23 maximum: 0.3 lead_len: minimum: 0.3 nominal: 0.4 maximum: 0.5 EP_size_x: minimum: 2.95 nominal: 3.1 maximum: 3.25 EP_size_y: minimum: 2.95 nominal: 3.1 maximum: 3.25 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.33 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 grid: [1.2, 1.2] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-32-1EP_5x5mm_P0.5mm_EP3.15x3.15mm: device_type: 'VQFN' size_source: 'https://www.ti.com/lit/ds/slvs589d/slvs589d.pdf#page=33' ipc_class: 'qfn' body_size_x: 5.0 +/- 0.15 body_size_y: 5.0 +/- 0.15 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: 3.15 +/- 0.1 EP_size_y: 3.15 +/- 0.1 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 VQFN-32-1EP_5x5mm_P0.5mm_EP3.5x3.5mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT4222H.pdf#page=40' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 5 tolerance: 0 body_size_y: nominal: 5 tolerance: 0 overall_height: nominal: 0.85 tolerance: 0.05 lead_width: nominal: 0.25 tolerance: [+0.05, -0.07] lead_len: nominal: 0.4 tolerance: 0.05 EP_size_x: nominal: 3.5 tolerance: 0.05 EP_size_y: nominal: 3.5 tolerance: 0.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.7 # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 8 num_pins_y: 8 #chamfer_edge_pins: 0.25 #pin_count_grid: #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-46-1EP_5x6mm_P0.4mm_EP2.8x3.8mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/lp5036.pdf#page=59' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: 4.9 .. 5.1 body_size_y: 5.9 .. 6.1 overall_height: 1.0 lead_width: 0.15 .. 0.25 lead_len: 0.25 .. 0.45 EP_size_x: nominal: 2.8 tolerance: 0.05 EP_size_y: nominal: 3.8 tolerance: 0.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 3] thermal_vias: count: [3, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 # bottom_pad_size: paste_avoid_via: False pitch: 0.4 num_pins_x: 10 num_pins_y: 13 #chamfer_edge_pins: 0.25 #pin_count_grid: #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-48-1EP_7x7mm_P0.5mm_EP5.15x5.15mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/cc1312r.pdf#page=48' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.9 #nominal: 7 maximum: 7.1 body_size_y: minimum: 6.9 #nominal: 7 maximum: 7.1 overall_height: #minimum: 0.8 #nominal: 0.85 maximum: 1 lead_width: minimum: 0.18 #nominal: 0.24 maximum: 0.3 lead_len: minimum: 0.3 #nominal: 0.3 maximum: 0.5 EP_size_x: nominal: 5.15 tolerance: 0.1 EP_size_y: nominal: 5.15 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [5, 5] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 #EP_paste_coverage: 0.7 #grid: [1.2, 1.2] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' VQFN-48-1EP_7x7mm_P0.5mm_EP4.1x4.1mm: device_type: 'VQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/cc430f5137.pdf#page=128' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 6.85 #nominal: 7 maximum: 7.15 body_size_y: minimum: 6.85 #nominal: 7 maximum: 7.15 overall_height: maximum: 1 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 4.1 tolerance: 0.1 EP_size_y: nominal: 4.1 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [3, 3] # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [4, 4] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 # EP_num_paste_pads: [2, 2] # paste_between_vias: 1 # paste_rings_outside: 1 #EP_paste_coverage: 0.7 #grid: [1.2, 1.2] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 12 num_pins_y: 12 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/qfn/wqfn.yaml ================================================ WQFN-14-1EP_2.5x2.5mm_P0.5mm_EP1.45x1.45mm: device_type: 'WQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.onsemi.com/pub/Collateral/FUSB302B-D.PDF#page=32' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 2.5 tolerance: 0.05 body_size_y: nominal: 2.5 tolerance: 0.05 overall_height: nominal: 0.75 tolerance: 0.05 lead_width: nominal: 0.24 tolerance: 0.06 lead_len: nominal: 0.3 tolerance: 0 # no tolerance given in datasheet EP_size_x: nominal: 1.45 tolerance: 0.05 EP_size_y: nominal: 1.45 tolerance: 0.05 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.7 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WQFN-16-1EP_3x3mm_P0.5mm_EP1.6x1.6mm: device_type: 'WQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.ti.com/lit/ds/symlink/tpa6132a2.pdf#page=24' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 2.85 maximum: 3.15 body_size_y: minimum: 2.85 maximum: 3.15 overall_height: maximum: 0.8 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 1.6 tolerance: 0.1 EP_size_y: nominal: 1.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WQFN-16-1EP_3x3mm_P0.5mm_EP1.75x1.75mm: device_type: 'WQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'https://www.onsemi.com/pub/Collateral/FUSB307B-D.PDF#page=56' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0 body_size_y: nominal: 3 tolerance: 0 overall_height: maximum: 0.8 lead_width: minimum: 0.18 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.4 EP_size_x: minimum: 1.65 maximum: 1.75 EP_size_x_overwrite: 1.75 EP_size_y: minimum: 1.65 maximum: 1.75 EP_size_y_overwrite: 1.75 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [2, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WQFN-16-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'WQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/ldc1312.pdf#page=59' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 0.8 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.6 tolerance: 0.1 EP_size_y: nominal: 2.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WQFN-24-1EP_4x4mm_P0.5mm_EP2.6x2.6mm: device_type: 'WQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/lm26480.pdf#page=39' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 0.8 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.6 tolerance: 0.1 EP_size_y: nominal: 2.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WQFN-24-1EP_4x4mm_P0.5mm_EP2.45x2.45mm: device_type: 'WQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/ts3a27518e.pdf#page=33' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 0.8 lead_width: minimum: 0.24 maximum: 0.34 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.45 tolerance: 0.1 EP_size_y: nominal: 2.45 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 6 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' WQFN-42-1EP_3.5x9mm_P0.5mm_EP2.05x7.55mm: device_type: 'WQFN' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/ts3l501e.pdf#page=23' ipc_class: 'qfn' # 'qfn_pull_back' body_size_x: minimum: 3.4 maximum: 3.6 body_size_y: minimum: 8.9 maximum: 9.1 overall_height: minimum: 0.7 maximum: 0.8 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.05 tolerance: 0.1 EP_size_y: nominal: 7.55 tolerance: 0.1 EP_num_paste_pads: [2, 7] thermal_vias: count: [3, 8] drill: 0.2 paste_via_clearance: 0.1 paste_avoid_via: False pitch: 0.5 num_pins_x: 4 num_pins_y: 17 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/vson.yaml ================================================ VSON-10_3x3mm_P0.5mm_EP1.2x2mm: device_type: 'VSON' library: Package_SON #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://rohmfs.rohm.com/en/products/databook/datasheet/ic/power/switching_regulator/bd8314nuv-e.pdf (Page 20)' ipc_class: 'qfn' # 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. # custom_name_format: body_size_x: nominal: 3 tolerance: 0.1 body_size_y: nominal: 3 tolerance: 0.1 lead_width_min: 0.21 lead_width_max: 0.3 lead_len_min: 0.3 lead_len_max: 0.5 # heel_reduction: 0.05 #for relatively large EP pads (increase clearance) EP_size_x_min: 1.1 EP_size_x: 1.2 EP_size_x_max: 1.3 EP_size_y_min: 1.9 EP_size_y: 2.0 EP_size_y_max: 2.2 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] #heel_reduction: 0.05 #for relatively large EP pads (increase clearance) thermal_vias: count: [1, 2] drill: 0.3 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [2, 2] #paste_between_vias: 1 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/wdfn-8.yml ================================================ WDFN-8-1EP_6x5mm_P1.27mm_EP3.4x4mm: device_type: 'WDFN' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/8L_WDFN_5x6mm_MF_C04210B.pdf' ipc_class: 'qfn' body_size_x: nominal: 6.0 tolerance: 0 body_size_y: nominal: 5.0 tolerance: 0 lead_width_min: 0.35 lead_width_max: 0.48 lead_len_min: 0.50 lead_len_max: 0.70 EP_size_x: 3.4 EP_size_y: 4 EP_num_paste_pads: [2, 2] pitch: 1.27 num_pins_x: 0 num_pins_y: 4 ================================================ FILE: scripts/Packages/Package_NoLead__DFN_QFN_LGA_SON/size_definitions/wson.yaml ================================================ WSON-6-1EP_2x2mm_P0.65mm_EP1x1.6mm: device_type: 'WSON' library: Package_SON #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/tps61040.pdf#page=35' ipc_class: 'qfn_pull_back' #'qfn' | 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 1.9 maximum: 2.1 body_size_y: minimum: 1.9 maximum: 2.1 lead_width: minimum: 0.25 maximum: 0.35 lead_len: minimum: 0.2 maximum: 0.3 EP_size_x: nominal: 1 tolerance: 0.1 EP_size_y: nominal: 1.6 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [1, 2] thermal_vias: count: [1, 2] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 EP_num_paste_pads: [1, 2] # paste_between_vias: 1 # paste_rings_outside: 1 EP_paste_coverage: 0.75 grid: [1.1, 1.1] # bottom_pad_size: paste_avoid_via: False pitch: 0.65 num_pins_x: 0 num_pins_y: 3 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) SON-8-1EP_3.0x2.0mm_P0.5mm_EP1.4x1.6mm: device_type: 'SON' library: Package_SON #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.fujitsu.com/downloads/MICRO/fsa/pdf/products/memory/fram/MB85RS16-DS501-00014-6v0-E.pdf' ipc_class: 'qfn_pull_back' #'qfn' | 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. #body_size_x_min: 2.85 body_size_x: nominal: 3.0 tolerance: 0.07 #body_size_x_max: 3.15 #body_size_y_min: 2.85 body_size_y: nominal: 2.0 tolerance: 0.07 #body_size_y_max: 3.15 lead_width_min: 0.20 lead_width_max: 0.30 lead_len_min: 0.33 lead_len_max: 0.47 EP_size_x: 1.4 EP_size_y: 1.6 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 0.50 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) WSON-8-1EP_3.0x2.5mm_P0.5mm_EP1.2x1.5mm: device_type: 'WSON' suffix: '_PullBack' library: Package_SON size_source: 'http://www.ti.com/lit/ml/mpds400/mpds400.pdf' ipc_class: 'qfn_pull_back' #'qfn' | 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. body_size_x: nominal: 3.0 tolerance: 0.1 body_size_y: nominal: 2.5 tolerance: 0.1 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: nominal: 0.5 tolerance: 0.1 lead_to_edge: 0.1 EP_size_x: nominal: 1.2 tolerance: 0.1 EP_size_y: nominal: 1.5 tolerance: 0.1 EP_num_paste_pads: [2, 2] pitch: 0.50 num_pins_x: 0 num_pins_y: 4 thermal_vias: count: [2, 2] drill: 0.2 paste_via_clearance: 0.1 EP_paste_coverage: 0.75 paste_avoid_via: False WSON-8-1EP_6x5mm_P1.27mm_EP3.4x4.0mm: device_type: 'WSON' library: Package_SON #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/AppNotes/S72030.pdf' ipc_class: 'qfn_pull_back' #'qfn' | 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. #body_size_x_min: 2.85 body_size_x: nominal: 6 tolerance: 0 #body_size_x_max: 3.15 #body_size_y_min: 2.85 body_size_y: nominal: 5 tolerance: 0 #body_size_y_max: 3.15 lead_width_min: 0.35 lead_width_max: 0.48 lead_len_min: 0.5 lead_len_max: 0.75 EP_size_x: 3.4 EP_size_y: 4.0 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 1.27 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) WSON-8-1EP_6x5mm_P1.27mm_E3.4x4.3mm: device_type: 'WSON' library: Package_SON #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.winbond.com/resource-files/w25q32jv%20revg%2003272018%20plus.pdf (page 68)' ipc_class: 'qfn_pull_back' #'qfn' | 'qfn_pull_back' #ipc_density: 'least' #overwrite global value for this device. #body_size_x_min: 2.85 body_size_x: minimum: 5.9 nominal: 6 maximum: 6.1 body_size_y: minimum: 4.9 nominal: 5 maximum: 5.1 overall_height: minimum: 0.70 nominal: 0.75 maximum: 0.80 lead_width: minimum: 0.35 nominal: 0.4 maximum: 0.48 lead_len: minimum: 0.55 nominal: 0.6 maximum: 0.65 EP_size_x: minimum: 3.35 nominal: 3.4 maximum: 3.45 EP_size_y: minimum: 4.25 nominal: 4.3 maximum: 4.35 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] pitch: 1.27 num_pins_x: 0 num_pins_y: 4 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) WSON-8-1EP_4x4mm_P0.8mm_EP2.2x3mm: device_type: 'WSON' library: Package_SON size_source: 'https://www.ti.com/lit/ds/symlink/lp2987.pdf#page=26' # NGN0008A ipc_class: 'qfn_pull_back' body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 0.8 lead_width: maximum: 0.35 minimum: 0.25 lead_len: minimum: 0.4 maximum: 0.6 # This value is tricky. The recommended footprint has pad-center-to-center as 3.3mm # But Adding EP + EP-Pad-Distance + Pad (2.2 + (0.2+0.15)*2 + 0.5 gives 3.4mm. # The above addition works on reference-dimensions. So is not to be trusted. lead_center_to_center_x: 3.3 EP_size_x: nominal: 2.2 tolerance: 0.05 EP_size_y: nominal: 3 tolerance: 0.05 EP_num_paste_pads: [2, 2] thermal_vias: count: [1, 3] drill: 0.2 paste_via_clearance: 0.1 paste_avoid_via: True pitch: 0.8 num_pins_x: 0 num_pins_y: 4 WSON-8-1EP_4x4mm_P0.8mm_EP1.98x3mm: device_type: 'WSON' library: Package_SON size_source: 'https://www.ti.com/lit/ds/symlink/lm5017.pdf#page=34' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' body_size_x: nominal: 4.0 tolerance: 0.1 body_size_y: nominal: 4.0 tolerance: 0.1 overall_height: maximum: 0.8 lead_width: 0.3 +/- 0.05 lead_len: 0.4 +/- 0.1 EP_size_x: nominal: 1.98 tolerance: 0.1 EP_size_y: nominal: 3 tolerance: 0.1 EP_num_paste_pads: [2, 2] thermal_vias: count: [1, 3] drill: 0.2 paste_via_clearance: 0.1 paste_avoid_via: True pitch: 0.8 num_pins_x: 0 num_pins_y: 4 WSON-8-1EP_4x4mm_P0.8mm_EP2.6x3mm: device_type: 'WSON' library: Package_SON size_source: 'https://www.ti.com/lit/ds/symlink/lp2951-n.pdf#page=43' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: maximum: 0.8 lead_width: maximum: 0.35 minimum: 0.25 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.6 tolerance: 0.05 EP_size_y: nominal: 3 tolerance: 0.05 EP_num_paste_pads: [2, 2] thermal_vias: count: [1, 3] drill: 0.2 paste_via_clearance: 0.1 paste_avoid_via: True pitch: 0.8 num_pins_x: 0 num_pins_y: 4 WSON-8-1EP_3x3mm_P0.5mm_EP1.2x2mm: device_type: 'WSON' library: Package_SON size_source: 'http://www.ti.com/lit/ds/symlink/lp2951.pdf#page=27' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' body_size_x: minimum: 2.9 maximum: 3.1 body_size_y: minimum: 2.9 maximum: 3.1 overall_height: minimum: 0.7 maximum: 0.8 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: minimum: 0.4 maximum: 0.6 EP_size_x: nominal: 1.2 tolerance: 0.1 EP_size_y: nominal: 2 tolerance: 0.1 EP_num_paste_pads: [1, 2] thermal_vias: count: [2, 3] drill: 0.2 paste_via_clearance: 0.1 EP_paste_coverage: 0.75 paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 4 WSON-8-1EP_3x3mm_P0.5mm_EP1.45x2.4mm: device_type: 'WSON' library: Package_SON size_source: 'https://www.ti.com/lit/ds/symlink/ina333.pdf#page=30' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' body_size_x: minimum: 2.9 maximum: 3.1 body_size_y: minimum: 2.9 maximum: 3.1 overall_height: minimum: 0.7 maximum: 0.8 lead_width: nominal: 0.25 tolerance: 0.05 lead_len: minimum: 0.4 maximum: 0.6 EP_size_x: nominal: 1.45 tolerance: 0.1 EP_size_y: nominal: 2.4 tolerance: 0.1 EP_num_paste_pads: [1, 2] thermal_vias: count: [2, 3] drill: 0.2 paste_via_clearance: 0.1 EP_paste_coverage: 0.75 paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 4 WSON-10-1EP_2.5x2.5mm_P0.5mm_EP1.2x2mm: device_type: 'WSON' library: Package_SON #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/gpn/tps63030#page=24' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' #custom_name_format: 'Texas_S-PWSON-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 2.4 maximum: 2.6 body_size_y: minimum: 2.4 maximum: 2.6 overall_height: minimum: 0.6 maximum: 0.8 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.35 maximum: 0.45 EP_size_x: nominal: 1.2 tolerance: 0.1 EP_size_y: nominal: 2 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [2, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] # paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 5 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) WSON-12-1EP_4x4mm_P0.5mm_EP2.6x3mm: device_type: 'WSON' library: Package_SON #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.ti.com/lit/ds/symlink/ldc1312.pdf#page=62' ipc_class: 'qfn' #'qfn' | 'qfn_pull_back' #custom_name_format: 'Texas_S-PWSON-N{pincount}_EP{ep_size_x:g}x{ep_size_y:g}mm{vias:s}' #ipc_density: 'least' #overwrite global value for this device. body_size_x: minimum: 3.9 maximum: 4.1 body_size_y: minimum: 3.9 maximum: 4.1 overall_height: minimum: 0.8 maximum: 1 lead_width: minimum: 0.2 maximum: 0.3 lead_len: minimum: 0.3 maximum: 0.5 EP_size_x: nominal: 2.6 tolerance: 0.1 EP_size_y: nominal: 3 tolerance: 0.1 # EP_paste_coverage: 0.65 EP_num_paste_pads: [2, 2] thermal_vias: count: [3, 3] drill: 0.2 # min_annular_ring: 0.15 paste_via_clearance: 0.1 #EP_num_paste_pads: [2, 2] # paste_between_vias: 2 #paste_rings_outside: 1 EP_paste_coverage: 0.75 #grid: [1, 1] # bottom_pad_size: paste_avoid_via: False pitch: 0.5 num_pins_x: 0 num_pins_y: 6 #chamfer_edge_pins: 0.25 #pin_count_grid: #pad_length_addition: 0.5 #suffix: '_PullBack' #include_suffix_in_3dpath: 'False' #include_pad_size: 'fp_name_only' # 'both' | 'none' (default) ================================================ FILE: scripts/Packages/Package_PLCC/ipc_plcc_jLead_generator.py ================================================ #!/usr/bin/env python import sys import os import argparse import yaml import math sys.path.append(os.path.join(sys.path[0], "..", "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA sys.path.append(os.path.join(sys.path[0], "..", "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields ipc_density = 'nominal' ipc_doc_file = '../ipc_definitions.yaml' category = 'LCC' def roundToBase(value, base): return round(value/base) * base def params_inch_to_metric(device_params): for key in device_params: if type(device_params[key]) in [int, float] and 'num_' not in key: device_params[key] = device_params[key]*25.4 class QFP(): def __init__(self, configuration): self.configuration = configuration with open(ipc_doc_file, 'r') as ipc_stream: try: self.ipc_defintions = yaml.safe_load(ipc_stream) except yaml.YAMLError as exc: print(exc) def calcPadDetails(self, device_params, ipc_data, ipc_round_base): # Zmax = Lmin + 2JT + √(CL^2 + F^2 + P^2) # Gmin = Smax − 2JH − √(CS^2 + F^2 + P^2) # Xmax = Wmin + 2JS + √(CW^2 + F^2 + P^2) # Some manufacturers do not list the terminal spacing (S) in their datasheet but list the terminal lenght (T) # Then one can calculate # Stol(RMS) = √(Ltol^2 + 2*^2) # Smin = Lmin - 2*Tmax # Smax(RMS) = Smin + Stol(RMS) F = self.configuration.get('manufacturing_tolerance', 0.1) P = self.configuration.get('placement_tolerance', 0.05) lead_width_tol = device_params['lead_width_max'] - device_params['lead_width_min'] def calcPadLength(overall, body, lead_inside=None, lead_center=None): overall_tol = overall['max']-overall['min'] if lead_inside: Tmin = (overall['max'] - lead_inside['max'])/2 Tmax = (overall['min'] - lead_inside['min'])/2 Ttol = Tmax - Tmin inside_tol = lead_inside['max'] - lead_inside['min'] Stol_RMS = math.sqrt(overall_tol**2+inside_tol**2) Smax_RMS = lead_inside['min'] + Stol_RMS elif lead_center: body_tol = body['max']-body['min'] Tmin = (body['max'] - lead_center['max']) Tmax = (body['min'] - lead_center['min']) Ttol = Tmax - Tmin center_tol = lead_center['max'] - lead_center['min'] Stol_RMS = math.sqrt(body_tol**2+center_tol**2) Smax_RMS = body['max'] - 2*Tmin + Stol_RMS else: lead_len_tol = device_params['lead_len_max'] - device_params['lead_len_min'] Stol_RMS = math.sqrt(overall_tol**2+2*(lead_len_tol**2)) Smin = overall['min'] - 2*device_params['lead_len_max'] Smax_RMS = Smin + Stol_RMS Gmin = Smax_RMS - 2*ipc_data['heel'] - math.sqrt(Stol_RMS**2 + F**2 + P**2) Zmax = overall['min'] + 2*ipc_data['toe'] + math.sqrt(overall_tol**2 + F**2 + P**2) Zmax = roundToBase(Zmax, ipc_round_base['toe']) Gmin = roundToBase(Gmin, ipc_round_base['heel']) Zmax += device_params.get('pad_length_addition', 0) return Gmin, Zmax overall_x={ 'min':device_params.get('overall_size_x_min', device_params.get('overall_size_x')), 'max':device_params.get('overall_size_x_max', device_params.get('overall_size_x')) } overall_y={ 'min':device_params.get('overall_size_y_min', device_params.get('overall_size_y')), 'max':device_params.get('overall_size_y_max', device_params.get('overall_size_y')) } body_x={ 'min':device_params.get('body_size_x_min', device_params.get('body_size_x')), 'max':device_params.get('body_size_x_max', device_params.get('body_size_x')) } body_y={ 'min':device_params.get('body_size_y_min', device_params.get('body_size_y')), 'max':device_params.get('body_size_y_max', device_params.get('body_size_y')) } if 'lead_inside_x_min' in device_params: Gmin_x, Zmax_x = calcPadLength( overall=overall_x, body=body_x, lead_inside={ 'min':device_params['lead_inside_x_min'], 'max':device_params['lead_inside_x_max']} ) Gmin_y, Zmax_y = calcPadLength( overall=overall_y, body=body_y, lead_inside={ 'min':device_params['lead_inside_y_min'], 'max':device_params['lead_inside_y_max']} ) elif 'lead_center_distance_x_min' in device_params: Gmin_x, Zmax_x = calcPadLength( overall=overall_x, body=body_x, lead_center={ 'min':device_params['lead_center_distance_x_min'], 'max':device_params['lead_center_distance_x_max']} ) Gmin_y, Zmax_y = calcPadLength( overall=overall_y, body=body_y, lead_center={ 'min':device_params['lead_center_distance_y_min'], 'max':device_params['lead_center_distance_y_max']} ) else: Gmin_x, Zmax_x = calcPadLength( overall=overall_x, body=body_x ) Gmin_y, Zmax_y = calcPadLength( overall=overall_y, body=body_y ) Xmax = device_params['lead_width_min'] + 2*ipc_data['side'] + math.sqrt(lead_width_tol**2 + F**2 + P**2) Xmax = roundToBase(Xmax, ipc_round_base['side']) Pad = {} Pad['first'] = {'start':[-((device_params['num_pins_x']-1)%2)/2*device_params['pitch'], -(Zmax_y+Gmin_y)/4], 'size':[Xmax,(Zmax_y-Gmin_y)/2]} Pad['left'] = {'center':[-(Zmax_x+Gmin_x)/4, 0], 'size':[(Zmax_x-Gmin_x)/2,Xmax]} Pad['right'] = {'center':[(Zmax_x+Gmin_x)/4, 0], 'size':[(Zmax_x-Gmin_x)/2,Xmax]} Pad['top'] = {'start':[(device_params['num_pins_x']-1)/2*device_params['pitch'],-(Zmax_y+Gmin_y)/4], 'size':[Xmax,(Zmax_y-Gmin_y)/2]} Pad['bottom'] = {'center':[0,(Zmax_y+Gmin_y)/4], 'size':[Xmax,(Zmax_y-Gmin_y)/2]} return Pad def generateFootprint(self, device_params): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) lib_name = self.configuration['lib_name_format_string'].format(category=category) if 'body_size_x' in device_params: size_x = device_params['body_size_x'] else: size_x = (device_params['body_size_x_max'] + device_params['body_size_x_min'])/2 if 'body_size_y' in device_params: size_y = device_params['body_size_y'] else: size_y = (device_params['body_size_y_max'] + device_params['body_size_y_min'])/2 pincount = device_params['num_pins_x']*2 + device_params['num_pins_y']*2 ipc_reference = 'ipc_spec_j_lead' ipc_data_set = self.ipc_defintions[ipc_reference][ipc_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pad_details = self.calcPadDetails(device_params, ipc_data_set, ipc_round_base) suffix = device_params.get('suffix', '').format(pad_x=pad_details['left']['size'][0], pad_y=pad_details['left']['size'][1]) suffix_3d = suffix if device_params.get('include_suffix_in_3dpath', 'True') == 'True' else "" model3d_path_prefix = self.configuration.get('3d_model_prefix','${KISYS3DMOD}') name_format = self.configuration['fp_name_format_string'] fp_name = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], suffix=suffix ).replace('__','_').lstrip('_') fp_name_2 = name_format.format( man=device_params.get('manufacturer',''), mpn=device_params.get('part_number',''), pkg=device_params['device_type'], pincount=pincount, size_y=size_y, size_x=size_x, pitch=device_params['pitch'], suffix=suffix_3d ).replace('__','_').lstrip('_') model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'\ .format( model3d_path_prefix=model3d_path_prefix, lib_name=lib_name, fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription( "{manufacturer} {mpn} {package}, {pincount} Pin ({datasheet}), generated with kicad-footprint-generator {scriptname}"\ .format( manufacturer = device_params.get('manufacturer',''), package = device_params['device_type'], mpn = device_params.get('part_number',''), pincount = pincount, datasheet = device_params['size_source'], scriptname = os.path.basename(__file__).replace(" ", " ") ).lstrip()) kicad_mod.setTags(self.configuration['keyword_fp_string']\ .format( man=device_params.get('manufacturer',''), package=device_params['device_type'], category=category ).lstrip()) kicad_mod.setAttribute('smd') pad_shape_details = {} pad_shape_details['shape'] = Pad.SHAPE_ROUNDRECT pad_shape_details['radius_ratio'] = configuration.get('round_rect_radius_ratio', 0) if 'round_rect_max_radius' in configuration: pad_shape_details['maximum_radius'] = configuration['round_rect_max_radius'] init = 1 kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=int(math.ceil(device_params['num_pins_x']/2)), x_spacing=-device_params['pitch'], y_spacing=0, **pad_details['first'], **pad_shape_details)) init += int(math.ceil(device_params['num_pins_x']/2)) kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=device_params['pitch'], **pad_details['left'], **pad_shape_details)) init += device_params['num_pins_y'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=device_params['pitch'], **pad_details['bottom'], **pad_shape_details)) init += device_params['num_pins_x'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=-device_params['pitch'], **pad_details['right'], **pad_shape_details)) init += device_params['num_pins_y'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=int(math.floor(device_params['num_pins_x']/2)), y_spacing=0, x_spacing=-device_params['pitch'], **pad_details['top'], **pad_shape_details)) body_edge = { 'left': -size_x/2, 'right': size_x/2, 'top': -size_y/2, 'bottom': size_y/2 } bounding_box = { 'left': pad_details['left']['center'][0] - pad_details['left']['size'][0]/2, 'right': pad_details['right']['center'][0] + pad_details['right']['size'][0]/2, 'top': pad_details['top']['start'][1] - pad_details['top']['size'][1]/2, 'bottom': pad_details['bottom']['center'][1] + pad_details['bottom']['size'][1]/2 } pad_width = pad_details['top']['size'][0] p1_x = pad_details['first']['start'][0] # ############################ SilkS ################################## silk_pad_offset = configuration['silk_pad_clearance'] + configuration['silk_line_width']/2 silk_offset = configuration['silk_fab_offset'] sx1 = -(device_params['pitch']*(device_params['num_pins_x']-1)/2.0 + pad_width/2.0 + silk_pad_offset) sy1 = -(device_params['pitch']*(device_params['num_pins_y']-1)/2.0 + pad_width/2.0 + silk_pad_offset) poly_silk = [ {'x': sx1, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': sy1} ] kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", y_mirror=0)) kicad_mod.append(PolygoneLine( polygone=poly_silk, width=configuration['silk_line_width'], layer="F.SilkS", x_mirror=0, y_mirror=0)) silk_off_45 = silk_offset/sqrt(2) poly_silk_tl = [ {'x': sx1, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']+device_params['body_chamfer']-silk_off_45, 'y': body_edge['top']-silk_offset}, {'x': body_edge['left']-silk_offset, 'y': body_edge['top']+device_params['body_chamfer']-silk_off_45}, {'x': body_edge['left']-silk_offset, 'y': sy1} ] kicad_mod.append(PolygoneLine( polygone=poly_silk_tl, width=configuration['silk_line_width'], layer="F.SilkS")) # # ######################## Fabrication Layer ########################### fab_bevel_size = min(configuration['fab_bevel_size_absolute'], configuration['fab_bevel_size_relative']*min(size_x, size_y)) fab_bevel_y = fab_bevel_size/sqrt(2) poly_fab = [ {'x': p1_x, 'y': body_edge['top']+fab_bevel_y}, {'x': p1_x+fab_bevel_size/2, 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['top']}, {'x': body_edge['right'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['bottom']}, {'x': body_edge['left'], 'y': body_edge['top']+device_params['body_chamfer']}, {'x': body_edge['left']+device_params['body_chamfer'], 'y': body_edge['top']}, {'x': p1_x-fab_bevel_size/2, 'y': body_edge['top']}, {'x': p1_x, 'y': body_edge['top']+fab_bevel_y} ] kicad_mod.append(PolygoneLine( polygone=poly_fab, width=configuration['fab_line_width'], layer="F.Fab")) # # ############################ CrtYd ################################## off = ipc_data_set['courtyard'] grid = configuration['courtyard_grid'] off_45 = off*math.tan(math.radians(45.0/2)) cy1=roundToBase(bounding_box['top']-off, grid) cy2=roundToBase(body_edge['top']-off, grid) cy3=-roundToBase( device_params['pitch']*(device_params['num_pins_y']-1)/2.0 + pad_width/2.0 + off, grid) cy4=roundToBase(body_edge['top']+device_params['body_chamfer']-off_45, grid) cx1=-roundToBase( device_params['pitch']*(device_params['num_pins_x']-1)/2.0 + pad_width/2.0 + off, grid) cx2=roundToBase(body_edge['left']-off, grid) cx3=roundToBase(bounding_box['left']-off, grid) cx4=roundToBase(body_edge['left']+device_params['body_chamfer']-off_45, grid) crty_poly_tl = [ {'x':0, 'y':cy1}, {'x':cx1, 'y':cy1}, {'x':cx1, 'y':cy2}, {'x':cx2, 'y':cy2}, {'x':cx2, 'y':cy3}, {'x':cx3, 'y':cy3}, {'x':cx3, 'y':0} ] kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], y_mirror=0)) kicad_mod.append(PolygoneLine(polygone=crty_poly_tl, layer='F.CrtYd', width=configuration['courtyard_line_width'], x_mirror=0, y_mirror=0)) crty_poly_tl_ch = [ {'x':0, 'y':cy1}, {'x':cx1, 'y':cy1}, {'x':cx1, 'y':cy2}, {'x':cx4, 'y':cy2}, {'x':cx2, 'y':cy4}, {'x':cx2, 'y':cy3}, {'x':cx3, 'y':cy3}, {'x':cx3, 'y':0} ] kicad_mod.append(PolygoneLine(polygone=crty_poly_tl_ch, layer='F.CrtYd', width=configuration['courtyard_line_width'])) # ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges=body_edge, courtyard={'top': cy1, 'bottom': -cy1}, fp_name=fp_name, text_y_inside_position='center') ##################### Output and 3d model ############################ kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('files', metavar='file', type=str, nargs='+', help='list of files holding information about what devices should be created.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='../package_config_KLCv3.yaml') parser.add_argument('--density', type=str, nargs='?', help='Density level (L,N,M)', default='N') parser.add_argument('--ipc_doc', type=str, nargs='?', help='IPC definition document', default='../ipc_definitions.yaml') parser.add_argument('--force_rectangle_pads', action='store_true', help='Force the generation of rectangle pads instead of rounded rectangle') args = parser.parse_args() if args.density == 'L': ipc_density = 'least' elif args.density == 'M': ipc_density = 'most' ipc_doc_file = args.ipc_doc with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) if args.force_rectangle_pads: configuration['round_rect_max_radius'] = None configuration['round_rect_radius_ratio'] = 0 for filepath in args.files: qfp = QFP(configuration) with open(filepath, 'r') as command_stream: try: cmd_file = yaml.safe_load(command_stream) except yaml.YAMLError as exc: print(exc) for pkg in cmd_file: if cmd_file[pkg].get('units', 'mm') == 'inches': params_inch_to_metric(cmd_file[pkg]) qfp.generateFootprint(cmd_file[pkg]) ================================================ FILE: scripts/Packages/Package_PLCC/plcc_jLead_definitions.yaml ================================================ PLCC_32: device_type: 'PLCC' # units: 'inches' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://ww1.microchip.com/downloads/en/DeviceDoc/doc0015.pdf' #overall_size_x: 0.69 overall_size_x_min: 12.319 overall_size_x_max: 12.573 #overall_size_y: 0.69 overall_size_y_min: 14.859 overall_size_y_max: 15.113 #body_size_x: 0.653 body_size_x_min: 11.354 body_size_x_max: 11.506 #body_size_y: 0.653 body_size_y_min: 13.894 body_size_y_max: 14.046 body_chamfer: 1.14 lead_width_min: 0.330 lead_width_max: 0.533 # lead_len_min: 0.45 # lead_len_max: 0.75 # lead_inside_x: 0.61 # lead_inside_x_min: 0.59 # lead_inside_x_max: 0.63 # lead_inside_y: 0.61 # lead_inside_y_min: 0.59 # lead_inside_y_max: 0.63 lead_center_distance_x_min: 9.906 lead_center_distance_x_max: 10.922 lead_center_distance_y_min: 12.471 lead_center_distance_y_max: 13.487 pitch: 1.27 num_pins_x: 7 num_pins_y: 9 #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' PLCC_44: device_type: 'PLCC' units: 'inches' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' overall_size_x: 0.69 overall_size_x_min: 0.685 overall_size_x_max: 0.695 overall_size_y: 0.69 overall_size_y_min: 0.685 overall_size_y_max: 0.695 body_size_x: 0.653 body_size_x_min: 0.65 body_size_x_max: 0.656 body_size_y: 0.653 body_size_y_min: 0.65 body_size_y_max: 0.656 body_chamfer: 0.045 lead_width_min: 0.013 lead_width_max: 0.021 # lead_len_min: 0.45 # lead_len_max: 0.75 lead_inside_x: 0.61 lead_inside_x_min: 0.59 lead_inside_x_max: 0.63 lead_inside_y: 0.61 lead_inside_y_min: 0.59 lead_inside_y_max: 0.63 pitch: 0.05 num_pins_x: 11 num_pins_y: 11 #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' PLCC_68: device_type: 'PLCC' units: 'inches' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' overall_size_x: 0.99 overall_size_x_min: 0.985 overall_size_x_max: 0.995 overall_size_y: 0.99 overall_size_y_min: 0.985 overall_size_y_max: 0.995 body_size_x: 0.954 body_size_x_min: 0.95 body_size_x_max: 0.958 body_size_y: 0.954 body_size_y_min: 0.95 body_size_y_max: 0.958 body_chamfer: 0.045 lead_width_min: 0.013 lead_width_max: 0.021 # lead_len_min: 0.45 # lead_len_max: 0.75 lead_inside_x: 0.91 lead_inside_x_min: 0.89 lead_inside_x_max: 0.93 lead_inside_y: 0.91 lead_inside_y_min: 0.89 lead_inside_y_max: 0.93 pitch: 0.05 num_pins_x: 17 num_pins_y: 17 #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' PLCC_84: device_type: 'PLCC' units: 'inches' #manufacturer: 'man' #part_number: 'mpn' size_source: 'http://www.microsemi.com/index.php?option=com_docman&task=doc_download&gid=131095' overall_size_x: 1.19 overall_size_x_min: 1.185 overall_size_x_max: 1.195 overall_size_y: 1.19 overall_size_y_min: 1.185 overall_size_y_max: 1.195 body_size_x: 1.154 body_size_x_min: 1.15 body_size_x_max: 1.158 body_size_y: 1.154 body_size_y_min: 1.15 body_size_y_max: 1.158 body_chamfer: 0.045 lead_width_min: 0.013 lead_width_max: 0.021 # lead_len_min: 0.45 # lead_len_max: 0.75 lead_inside_x: 1.11 lead_inside_x_min: 1.09 lead_inside_x_max: 1.13 lead_inside_y: 1.11 lead_inside_y_min: 1.09 lead_inside_y_max: 1.13 pitch: 0.05 num_pins_x: 21 num_pins_y: 21 #pad_length_addition: 0.5 #suffix: '_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder' #include_suffix_in_3dpath: 'False' ================================================ FILE: scripts/Packages/TO_SOT_Packages_SMD/DPAK.py ================================================ import sys import os import argparse import yaml import pprint sys.path.append(os.path.join(sys.path[0], "../../..")) # enable package import from parent directory from KicadModTree import * # NOQA class Dimensions(object): def __init__(self, base, variant, cut_pin=False, tab_linked=False): # FROM KLC self.fab_line_width_mm = 0.1 self.silk_line_width_mm = 0.12 self.courtyard_line_width_mm = 0.05 self.courtyard_clearance_mm = 0.25 self.courtyard_precision_mm = 0.01 # PIN NUMBERING self.centre_pin = 1 + variant['pins'] // 2 self.tab_pin_number= self.centre_pin if (tab_linked or cut_pin) else variant['pins'] + 1 # NAME self.name = self.footprint_name(base['series'], (variant['pins'] - 1) if cut_pin else variant['pins'], not cut_pin, self.tab_pin_number) # PADS self.pad_1_centre_x_mm = (variant['pad']['x_mm'] / 2.0) - (base['footprint']['x_mm'] / 2.0) self.pad_1_centre_y_mm = -variant['pitch_mm'] * (variant['pins'] - 1) / 2.0 self.tab_centre_x_mm = (base['footprint']['x_mm'] - base['footprint']['tab']['x_mm']) / 2.0 self.tab_centre_y_mm = 0.0 self.split_paste = (base['footprint']['split_paste'] == 'on') # FAB OUTLINE self.device_offset_x_mm = base['device']['x_mm'] / 2.0 # x coordinate of RHS of device self.tab_project_x_mm = base['device']['tab']['project_x_mm'] self.tab_offset_y_mm = base['device']['tab']['y_mm'] / 2.0 # y coordinate of bottom of tab self.body_x_mm = base['device']['body']['x_mm'] self.body_offset_y_mm = base['device']['body']['y_mm'] / 2.0 # y coordinate of bottom of body self.corner_mm = 1.0 # x and y size of chamfered corner on top left of body -- from KLC # COURTYARD self.biggest_x_mm = base['footprint']['x_mm'] self.biggest_y_mm = max(base['footprint']['tab']['y_mm'], base['device']['body']['y_mm'], 2.0 * self.pad_1_centre_y_mm + variant['pad']['y_mm']) self.courtyard_offset_x_mm = self.round_to(self.courtyard_clearance_mm + self.biggest_x_mm / 2.0, self.courtyard_precision_mm) self.courtyard_offset_y_mm = self.round_to(self.courtyard_clearance_mm + self.biggest_y_mm / 2.0, self.courtyard_precision_mm) # SILKSCREEN self.label_centre_x_mm = 0 self.label_centre_y_mm = self.courtyard_offset_y_mm + 1 self.silk_line_nudge_mm = 0.20 # amount to shift to stop silkscreen lines overlapping fab lines def round_to(self, n, precision): correction = 0.5 if n >= 0 else -0.5 return int(n / precision + correction) * precision def footprint_name(self, series, num_pins, add_tab, tab_number): tab_suffix = '_TabPin' if add_tab else '' pins = str(num_pins) tab = str(tab_number) if add_tab else '' name = '{p:s}-{ps:s}{ts:s}{tn:s}'.format(p=series, ps=pins, ts=tab_suffix, tn=tab) return name class DPAK(object): def __init__(self, config_file): self.SERIES = None self.config = None def load_config(self, config_file): try: devices = yaml.safe_load_all(open(config_file)) except FileNotFoundError as fnfe: print(fnfe) return config = None for dev in devices: if dev['base']['series'] == self.SERIES: config = dev break return config def add_properties(self, m, variant): m.setDescription('{bd:s}, {vd:s}'.format(bd=self.config['base']['description'], vd=variant['datasheet'])) m.setTags('{bk:s} {vk:s}'.format(bk=self.config['base']['keywords'], vk=variant['keywords'])) m.setAttribute('smd') return m def add_labels(self, m, variant, dim): m.append(Text(type='reference', text='REF**', size=[1,1], at=[dim.label_centre_x_mm, -dim.label_centre_y_mm], layer='F.SilkS')) m.append(Text(type='user', text='%R', size=[1,1], at=[0, 0], layer='F.Fab')) m.append(Text(type='value', text=dim.name, at=[dim.label_centre_x_mm, dim.label_centre_y_mm], layer='F.Fab')) return m def draw_tab(self, m, dim): right_x = dim.device_offset_x_mm left_x = right_x - dim.tab_project_x_mm top_y = -dim.tab_offset_y_mm bottom_y = -top_y tab_outline = [[left_x, top_y], [right_x, top_y], [right_x, bottom_y], [left_x, bottom_y]] m.append(PolygoneLine(polygone=tab_outline, layer='F.Fab', width=dim.fab_line_width_mm)) return m def draw_body(self, m, dim): right_x = dim.device_offset_x_mm - dim.tab_project_x_mm left_x = right_x - dim.body_x_mm top_y = -dim.body_offset_y_mm bottom_y = -top_y body_outline = [[right_x, top_y], [right_x, bottom_y], [left_x, bottom_y],\ [left_x, top_y + dim.corner_mm], [left_x + dim.corner_mm, top_y], [right_x, top_y]] m.append(PolygoneLine(polygone=body_outline, layer='F.Fab', width=dim.fab_line_width_mm)) return m def draw_pins(self, m, variant, dim, cut_pin): right_x = dim.device_offset_x_mm - dim.tab_project_x_mm - dim.body_x_mm left_x = right_x - variant['pin']['x_mm'] pin_1_top_y = dim.pad_1_centre_y_mm - (variant['pin']['y_mm'] / 2.0) body_corner_bottom_y = -dim.body_offset_y_mm + dim.corner_mm pin_1_extend = (body_corner_bottom_y - pin_1_top_y) if (pin_1_top_y < body_corner_bottom_y) else 0.0 for pin in range(1, variant['pins'] + 1): if not (pin == dim.centre_pin and cut_pin): top_y = dim.pad_1_centre_y_mm + ((pin - 1) * variant['pitch_mm']) - (variant['pin']['y_mm'] / 2.0) bottom_y = dim.pad_1_centre_y_mm + ((pin - 1) * variant['pitch_mm']) + (variant['pin']['y_mm'] / 2.0) pin_outline = [[right_x + (pin_1_extend if pin == 1 else 0), top_y], [left_x , top_y], [left_x, bottom_y], [right_x, bottom_y]] m.append(PolygoneLine(polygone=pin_outline, layer='F.Fab', width=dim.fab_line_width_mm)) return m def draw_outline(self, m, variant, dim, cut_pin=False): m = self.draw_tab(m, dim) m = self.draw_body(m, dim) m = self.draw_pins(m, variant, dim, cut_pin) return m def draw_markers(self, m, variant, dim): magic_number = 1.3 # TODO needs better name other_magic_number = 1.5 # TODO needs better name right_x = dim.device_offset_x_mm - dim.tab_project_x_mm - dim.body_x_mm + magic_number middle_x = dim.device_offset_x_mm - dim.tab_project_x_mm - dim.body_x_mm - dim.silk_line_nudge_mm left_x = dim.pad_1_centre_x_mm - variant['pad']['x_mm'] / 2.0 top_y = -dim.body_offset_y_mm - dim.silk_line_nudge_mm bottom_y = dim.pad_1_centre_y_mm - variant['pad']['y_mm'] / 2.0 - other_magic_number * dim.silk_line_nudge_mm top_marker = [[right_x, top_y], [middle_x, top_y], [middle_x, bottom_y], [left_x, bottom_y]] m.append(PolygoneLine(polygone=top_marker, layer='F.SilkS', width=dim.silk_line_width_mm)) top_y = -top_y bottom_y = -bottom_y left_x = dim.device_offset_x_mm - dim.tab_project_x_mm - dim.body_x_mm - magic_number bottom_marker = [[right_x, top_y], [middle_x, top_y], [middle_x, bottom_y], [left_x, bottom_y]] m.append(PolygoneLine(polygone=bottom_marker, layer='F.SilkS', width=dim.silk_line_width_mm)) return m def draw_pads(self, m, base, variant, dim, cut_pin): for pin in range(1, variant['pins'] + 1): if not (pin == dim.centre_pin and cut_pin): m.append(Pad(number=pin, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[dim.pad_1_centre_x_mm, dim.pad_1_centre_y_mm + (pin - 1) * variant['pitch_mm']], size=[variant['pad']['x_mm'], variant['pad']['y_mm']], layers=Pad.LAYERS_SMT)) tab_layers = Pad.LAYERS_SMT[:] if dim.split_paste: tab_layers.remove('F.Paste') paste_layers = Pad.LAYERS_SMT[:] paste_layers.remove('F.Mask') m.append(Pad(number=dim.tab_pin_number, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[dim.tab_centre_x_mm, dim.tab_centre_y_mm], size=[base['footprint']['tab']['x_mm'], base['footprint']['tab']['y_mm']], layers=tab_layers)) if dim.split_paste: gutter = base['footprint']['paste_gutter_mm'] paste_x_mm = (base['footprint']['tab']['x_mm'] - gutter) / 2.0 paste_y_mm = (base['footprint']['tab']['y_mm'] - gutter) / 2.0 paste_offset_x = (paste_x_mm + gutter) / 2.0 paste_offset_y = (paste_y_mm + gutter) / 2.0 left_x = dim.tab_centre_x_mm - paste_offset_x right_x = dim.tab_centre_x_mm + paste_offset_x top_y = dim.tab_centre_y_mm - paste_offset_y bottom_y = dim.tab_centre_y_mm + paste_offset_y for pad_xy in [[right_x, bottom_y], [left_x, top_y], [right_x, top_y], [left_x, bottom_y]]: m.append(Pad(number=dim.tab_pin_number, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=pad_xy, size=[paste_x_mm, paste_y_mm], layers=paste_layers)) return m def add_3D_model(self, m, base, dim): m.append( Model(filename="{p:s}/{n:s}.wrl".format(p=base['3d_prefix'], n=dim.name), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) return m def draw_courtyard(self, m ,dim): m.append(RectLine(start=[-dim.courtyard_offset_x_mm, -dim.courtyard_offset_y_mm], end=[dim.courtyard_offset_x_mm, dim.courtyard_offset_y_mm], layer='F.CrtYd', width=dim.courtyard_line_width_mm)) return m def build_footprint(self, base, variant, cut_pin=False, tab_linked=False, verbose=False): # calculate dimensions and other attributes specific to this variant dim = Dimensions(base, variant, cut_pin, tab_linked) # initialise footprint kicad_mod = Footprint(dim.name) kicad_mod = self.add_properties(kicad_mod, variant) kicad_mod = self.add_labels(kicad_mod, variant, dim) # create pads kicad_mod = self.draw_pads(kicad_mod, base, variant, dim, cut_pin) # create fab outline kicad_mod = self.draw_outline(kicad_mod, variant, dim, cut_pin) # create silkscreen marks and pin 1 marker kicad_mod = self.draw_markers(kicad_mod, variant, dim) # create courtyard kicad_mod = self.draw_courtyard(kicad_mod, dim) # add 3D model kicad_mod = self.add_3D_model(kicad_mod, base, dim) # print render tree if verbose: print(kicad_mod.getRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{:s}.kicad_mod'.format(dim.name)) def build_series(self, verbose=False): print('Building {p:s}'.format(p=self.config['base']['description'])) base = self.config['base'] for variant in self.config['variants']: if 'uncut' in variant['centre_pin']: self.build_footprint(base, variant, verbose=verbose) self.build_footprint(base, variant, tab_linked=True, verbose=verbose) if 'cut' in variant['centre_pin']: self.build_footprint(base, variant, cut_pin=True, verbose=verbose) class TO252(DPAK): def __init__(self, config_file): self.SERIES = 'TO-252' self.config = self.load_config(config_file) class TO263(DPAK): def __init__(self, config_file): self.SERIES = 'TO-263' self.config = self.load_config(config_file) class TO268(DPAK): def __init__(self, config_file): self.SERIES = 'TO-268' self.config = self.load_config(config_file) class ATPAK(DPAK): def __init__(self, config_file): self.SERIES = 'ATPAK' self.config = self.load_config(config_file) ================================================ FILE: scripts/Packages/TO_SOT_Packages_SMD/DPAK_README.md ================================================ # DPAK footprint generator Program to generate KiCad footprints using KicadModTree from https://github.com/pointhi/kicad-footprint-generator Devices included: - TO252 / DPAK - TO263 / D2PAK / DDPAK - TO268 / D3PAK - ATPAK ## Usage Download `kicad-footprint-generator` from https://github.com/pointhi/kicad-footprint-generator Install the following files in the folder `.../kicad-footprint-generator/scripts//`. ``` DPAK.py DPAK_config.yaml make_DPAK.py ``` To generate the footprints, run one of the following commands: ``` $ python3 ./make_DPAK.py # builds all device types $ python3 ./make_DPAK.py # builds specified type only, where type is one of TO252, TO263, TO268 or ATPAK ``` ## Configuration The program `make_DPAK.py` uses classes in `DPAK.py` to build the models. Design parameters for each device type and its variants (for example, number of pins, whether centre pin is cut) are contained in `DPAK_config.yaml`. The configuration for each device type is a separate YAML document in the configuration file (separated by `---`). The document for each type is broken into a `base:` section (values that apply to all devices in the family) and a `variants:` section with separate entries for each individual device. *The configuration file is shared with the 3D model generator program. Configuration items required for the 3D models are marked with `# 3D` in the descriptions below.* ### `base:` configuration ``` series: TO-252 # 3D ``` The package name is included in the names of the module files generated by the program. It can also be passed as a command line argument to limit which devices are generated. ``` description: 'TO-252 / DPAK SMD package' keywords: 'DPAK TO-252' ``` These strings are combined with the device-specific description and keywords (see below) and are included in the module file. ``` footprint: x_mm: 10.6 ``` The next part of the configuration file is about the footprint (i.e. the land pattern of copper pads). `x_mm` is the overall size of the footprint: the X distance between the left hand edge of the pin pads and the right hand edge of the tab pads. ``` tab: x_mm: 6.4 y_mm: 5.8 ``` This defines the size of the tab pad. ``` split_paste: 'on' paste_gutter_mm: 0.3 ``` If `split_paste` is `on`, the paste mask for the tab will be divided into four parts with a gap (gutter) between them. ``` device: x_mm: 9.9 # 3D ``` The next part of the configuration file is about the phyical device that sits on the footprint. `x_mm` is the overall size of the device: the X distance between the end of the pins and the right hand edge of the tab. ``` body: x_mm: 6.22 # 3D y_mm: 6.5 # 3D z_mm: 2.3 # 3D waist_z_mm: 1.2 # 3D marker_offset_x_mm: -1.5 # 3D colour: 'black body' # 3D tab: x_mm: 1.0 # 3D y_mm: 5.4 # 3D z_mm: 1.0 # 3D project_x_mm: 1.0 # 3D colour: 'metal grey pins' # 3D ``` These define the size of the body and tab. Tab `x_mm` includes the part of the tab under the body. `project_x_mm` is the part of the tab that projects outside the body. ``` marker: x_mm: 1.5 # 3D z_mm: 0.1 # 3D ``` These define the diameter and depth of the marker on top of the body. ``` pins: colour: 'metal grey pins' # 3D ``` Used for the 3D model. See below for configuration data for the pins on each variant. ``` 3d_prefix: '${KISYS3DMOD}/TO_SOT_Packages_SMD.3dshapes' ``` This string is added to the module to set the path to the 3D models folder. ### `variants:` configuration The variants section contains a list of one or more device definitions. ``` - pins: 3 # 3D pitch_mm: 2.28 # 3D ``` The `-` character starts the device definition. The first two settings are the number of pins and the pitch (Y distance between them). ``` pad: x_mm: 2.2 y_mm: 1.2 pin: x_mm: 2.7 y_mm: 0.75 # 3D z_mm: 0.5 # 3D cut_x_mm: 0.8 # 3D ``` These define the size of the pads and pins. The pin `x_mm` is the X distance from the end of an uncut pin to the device body, while `cut_x_mm` is the equivalent for a cut pin. ``` centre_pin: ['cut', 'uncut'] # 3D ``` This parameter contains either one or both of `'cut'` or '`uncut`'. If both are present, the program will generate two modules, one with a pad for the centre pin and one without. If just one is present, only one module will be generated. ``` keywords: 'DPAK-3 TO-252-3 SOT-428' datasheet: http://www.infineon.com/cms/en/product/packages/PG-TO252/PG-TO252-3-1/ ``` These strings are added to the base-level description and keywords (see above) and are included in the module. ================================================ FILE: scripts/Packages/TO_SOT_Packages_SMD/DPAK_config.yaml ================================================ # TO-252/DPAK SMD packages base: series: TO-252 description: 'TO-252/DPAK SMD package' keywords: 'DPAK TO-252' footprint: x_mm: 10.6 tab: x_mm: 6.4 y_mm: 5.8 split_paste: 'on' paste_gutter_mm: 0.3 device: x_mm: 9.9 body: x_mm: 6.22 y_mm: 6.5 z_mm: 2.3 waist_z_mm: 0.9 marker_offset_x_mm: -1.5 colour: 'black body' tab: x_mm: 5.24 y_mm: 5.4 z_mm: 0.5 project_x_mm: 1.0 colour: 'metal grey pins' marker: x_mm: 1.0 z_mm: 0.1 pins: colour: 'metal grey pins' 3d_prefix: '${KISYS3DMOD}/TO_SOT_Packages_SMD.3dshapes' variants: - pins: 3 pitch_mm: 2.28 pad: x_mm: 2.2 y_mm: 1.2 pin: x_mm: 2.7 y_mm: 0.75 z_mm: 0.5 centre_pin: ['cut', 'uncut'] keywords: 'DPAK-3 TO-252-3 SOT-428' datasheet: http://www.infineon.com/cms/en/product/packages/PG-TO252/PG-TO252-3-1/ - pins: 5 pitch_mm: 1.14 pad: x_mm: 2.2 y_mm: 0.8 pin: x_mm: 2.7 y_mm: 0.6 z_mm: 0.5 centre_pin: ['cut', 'uncut'] keywords: 'DPAK-5 TO-252-5' datasheet: http://www.infineon.com/cms/en/product/packages/PG-TO252/PG-TO252-5-11/ --- # TO-263/D2PAK SMD packages base: series: TO-263 description: 'TO-263/D2PAK/DDPAK SMD package' keywords: 'D2PAK DDPAK TO-263' footprint: x_mm: 16.15 tab: x_mm: 9.4 y_mm: 10.8 split_paste: 'on' paste_gutter_mm: 0.3 device: x_mm: 15.0 body: x_mm: 9.25 y_mm: 10.0 z_mm: 4.4 waist_z_mm: 2.4 marker_offset_x_mm: 0.0 colour: 'black body' tab: x_mm: 7.55 y_mm: 10.0 z_mm: 1.27 project_x_mm: 1.0 colour: 'metal grey pins' marker: x_mm: 2.5 z_mm: 0.1 pins: colour: 'metal grey pins' 3d_prefix: '${KISYS3DMOD}/TO_SOT_Packages_SMD.3dshapes' variants: - pins: 3 pitch_mm: 2.54 pad: x_mm: 4.6 y_mm: 1.1 pin: x_mm: 4.7 y_mm: 1.0 z_mm: 0.5 centre_pin: ['cut', 'uncut'] keywords: 'D2PAK-3 TO-263-3 SOT-404' datasheet: http://www.infineon.com/cms/en/product/packages/PG-TO263/PG-TO263-3-1/ - pins: 5 pitch_mm: 1.7 pad: x_mm: 4.6 y_mm: 1.1 pin: x_mm: 4.7 y_mm: 0.8 z_mm: 0.5 centre_pin: ['cut', 'uncut'] keywords: 'D2PAK-5 TO-263-5 SOT-426' datasheet: http://www.infineon.com/cms/en/product/packages/PG-TO263/PG-TO263-5-1/ - pins: 7 pitch_mm: 1.27 pad: x_mm: 4.6 y_mm: 0.8 pin: x_mm: 4.7 y_mm: 0.6 z_mm: 0.5 centre_pin: ['cut', 'uncut'] keywords: 'D2PAK-7 TO-263-7 SOT-427' datasheet: http://www.infineon.com/cms/en/product/packages/PG-TO263/PG-TO263-7-1/ --- # TO-268/D3PAK SMD packages base: series: TO-268 description: 'TO-268/D3PAK SMD package' keywords: 'D3PAK TO-268' footprint: x_mm: 21.95 tab: x_mm: 13.5 y_mm: 16.6 split_paste: 'on' paste_gutter_mm: 0.3 device: x_mm: 19.0 body: x_mm: 14.0 y_mm: 15.9 z_mm: 5.0 waist_z_mm: 2.8 marker_offset_x_mm: -1.0 colour: 'black body' tab: x_mm: 12.5 y_mm: 15.9 z_mm: 1.5 project_x_mm: 1.0 colour: 'metal grey pins' marker: x_mm: 2.5 z_mm: 0.1 pins: colour: 'metal grey pins' 3d_prefix: '${KISYS3DMOD}/TO_SOT_Packages_SMD.3dshapes' variants: - pins: 3 pitch_mm: 5.45 pad: x_mm: 5.0 y_mm: 3.0 pin: x_mm: 3.9 y_mm: 1.3 z_mm: 0.5 centre_pin: ['cut'] keywords: 'D3PAK-3 TO-268-3' datasheet: http://www.icbank.com/icbank_data/semi_package/to268aa_dim.pdf --- # ATPAK SMD packages base: series: ATPAK description: 'ATPAK SMD package' keywords: 'ATPAK' footprint: x_mm: 10.3 tab: x_mm: 6.7 y_mm: 6.5 split_paste: 'on' paste_gutter_mm: 0.3 device: x_mm: 9.5 body: x_mm: 7.3 y_mm: 6.5 z_mm: 1.5 waist_z_mm: 0.4 marker_offset_x_mm: 2.0 colour: 'black body' tab: x_mm: 6.05 y_mm: 6.5 z_mm: 0.4 project_x_mm: 0.5 colour: 'metal grey pins' marker: x_mm: 1.0 z_mm: 0.1 pins: colour: 'metal grey pins' 3d_prefix: '${KISYS3DMOD}/TO_SOT_Packages_SMD.3dshapes' variants: - pins: 3 pitch_mm: 2.3 pad: x_mm: 1.6 y_mm: 1.5 pin: x_mm: 1.7 y_mm: 0.6 z_mm: 0.4 centre_pin: ['cut'] keywords: '' datasheet: http://www.onsemi.com/pub/Collateral/ENA2192-D.PDF ================================================ FILE: scripts/Packages/TO_SOT_Packages_SMD/make_DPAK.py ================================================ #!/usr/bin/env python # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, import sys import os import argparse import yaml import pprint sys.path.append(os.path.join(sys.path[0], "../../..")) # enable package import from parent directory from KicadModTree import * # NOQA def get_args(): parser = argparse.ArgumentParser() parser.add_argument('--family', help='device type to build: TO-252 | TO-263 | TO-268 (default is all)', type=str, nargs=1) parser.add_argument('-v', '--verbose', help='show extra information while generating the footprint', action='store_true') return parser.parse_args() if __name__ == '__main__': print('Building DPAK') args = get_args() print('Rebuilding DPAK') from DPAK import DPAK, TO252, TO263, TO268, ATPAK CONFIG = 'DPAK_config.yaml' if args.family: if args.family[0] == 'TO252': build_list = [TO252(CONFIG)] elif args.family[0] == 'TO263': build_list = [TO263(CONFIG)] elif args.family[0] == 'TO268': build_list = [TO268(CONFIG)] elif args.family[0] == 'ATPAK': build_list = [ATPAK(CONFIG)] else: print('ERROR: family not recognised') build_list = [] else: build_list = [TO252(CONFIG), TO263(CONFIG), TO268(CONFIG), ATPAK(CONFIG)] for package in build_list: package.build_series(verbose=args.verbose) ================================================ FILE: scripts/Packages/TO_SOT_THT/TO_SOT_THT_generate.py ================================================ #usr/bin/env python import sys import os import math import time # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..","..")) # load kicad_mod path from KicadModTree import * # NOQA from tools import * from TO_THT_packages import * # vertical symbols for rectangular transistors def makeVERT(lib_name, pck, has3d=False, x_3d=[0, 0, 0], s_3d=[1,1,1], lptext="_LargePads", r_3d=[0, 0, 0]): padsize=pck.pad l_fabp = -pck.pin_offset_x t_fabp = -pck.pin_offset_z if pck.staggered_type >0: t_fabp=-pck.staggered_pin_offset_z w_fabp = pck.plastic[0] h_fabp = pck.plastic[2] w_fabm = pck.metal[0] h_fabm = pck.metal[2] l_slkp = l_fabp - slk_offset t_slkp = t_fabp - slk_offset w_slkp = w_fabp + 2 * slk_offset h_slkp = h_fabp + 2 * slk_offset w_slkm = w_fabm + 2 * slk_offset h_slkm = h_fabm + 2 * slk_offset l_mounth = l_fabp + pck.mounting_hole_pos[0] txt_x = l_slkp + max(w_slkp, w_slkm) / 2 # calculate pad positions pads=[] yshift=0 y1=0 y2=0 maxpiny=0 if pck.staggered_type == 1: y1 = pck.staggered_rm[0] yshift = -pck.staggered_rm[0] y2 = 0 maxpiny = pck.staggered_rm[0] if len(pck.staggered_pad)>0: padsize=pck.staggered_pad elif pck.staggered_type == 2: y1 = 0 yshift = 0 y2=pck.staggered_rm[0] maxpiny = pck.staggered_rm[0] if len(pck.staggered_pad) > 0: padsize = pck.staggered_pad pinwid = (pck.pins - 1) * pck.rm if len(pck.rm_list) > 0: pinwid = 0 for rm in pck.rm_list: pinwid = pinwid + rm l_crt = min(-padsize[0] / 2, l_fabp) - crt_offset t_crt = min(-padsize[1] / 2, t_fabp) - crt_offset w_crt = max(max(w_fabp, w_fabm), pinwid + padsize[0]) + 2 * crt_offset h_crt = max(t_fabp+max(h_fabp, h_fabm)+ crt_offset-t_crt, -t_crt + maxpiny + padsize[1] / 2 + crt_offset) y=y1 x = 0 for p in range(1, pck.pins + 1): if (p % 2) == 1: y = y1 else: y = y2 pads.append([x, y]) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm tag_items = ["Vertical", "RM {0}mm".format(pck.rm)] footprint_name = pck.name for t in pck.more_packnames: footprint_name = footprint_name + "_" + t footprint_name = footprint_name + "_Vertical" for t in pck.fpnametags: footprint_name = footprint_name + "_" + t if pck.staggered_type>0: footprint_name = footprint_name + "_Py{0}mm".format(pck.staggered_rm[0],3) if pck.largepads: tag_items.append("large Pads") footprint_name = footprint_name + lptext print(footprint_name) description = pck.name tags = pck.name for t in tag_items: description = description + ", " + t tags = tags + " " + t for t in pck.tags: description = description + ", " + t tags = tags + " " + t if len(pck.webpage)>0: description = description + ", see " + pck.webpage # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modt = Translation(0, yshift) kicad_mod.append(kicad_modt) # set general values kicad_modt.append(Text(type='reference', text='REF**', at=[txt_x, t_slkp - txt_offset], layer='F.SilkS')) kicad_modt.append(Text(type='user', text='%R', at=[txt_x, t_slkp - txt_offset], layer='F.Fab')) kicad_modt.append( Text(type='value', text=footprint_name, at=[txt_x, t_slkp + max(h_slkm, h_slkp, -t_slkp+h_crt+t_crt) + txt_offset], layer='F.Fab')) # create FAB-layer kicad_modt.append( RectLine(start=[l_fabp, t_fabp], end=[l_fabp + w_fabp, t_fabp + h_fabp], layer='F.Fab', width=lw_fab)) if (pck.metal[2] > 0): kicad_modt.append( Line(start=[l_fabp, t_fabp + h_fabm], end=[l_fabp + w_fabp, t_fabp + h_fabm], layer='F.Fab', width=lw_fab)) if pck.mounting_hole_diameter > 0: kicad_modt.append(Line(start=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp + h_fabm], layer='F.Fab', width=lw_fab)) kicad_modt.append(Line(start=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp + h_fabm], layer='F.Fab', width=lw_fab)) else: if pck.mounting_hole_diameter > 0: kicad_modt.append(Line(start=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp + h_fabp], layer='F.Fab', width=lw_fab)) kicad_modt.append(Line(start=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp + h_fabp], layer='F.Fab', width=lw_fab)) for p in range(0, len(pads)): yl1=t_fabp + h_fabp yl2=pads[p][1] if yl2>yl1: kicad_modt.append(Line(start=[pads[p][0], yl1], end=[pads[p][0], yl2], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer keepouts = [] for p in range(0,len(pads)): if p==0: keepouts=keepouts+addKeepoutRect(pads[p][0],pads[p][1],padsize[0]+2*slk_dist,padsize[1]+2*slk_dist) else: keepouts=keepouts+addKeepoutRound(pads[p][0],pads[p][1],padsize[0]+2*slk_dist,padsize[1]+2*slk_dist) #for ko in keepouts: # kicad_modt.append( # RectLine(start=[ko[0],ko[2]], end=[ko[1],ko[3]], layer='B.Fab', width=lw_fab)) addHLineWithKeepout(kicad_modt, l_slkp, l_slkp + w_slkp, t_slkp, 'F.SilkS', lw_slk, keepouts) addHLineWithKeepout(kicad_modt, l_slkp, l_slkp + w_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_slkp, t_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_slkp + w_slkp, t_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) if (pck.metal[2] > 0): addHLineWithKeepout(kicad_modt, l_slkp, l_slkp + w_slkp, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) if pck.mounting_hole_diameter > 0: addVLineWithKeepout(kicad_modt, l_mounth - pck.mounting_hole_diameter / 2, t_slkp, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_mounth + pck.mounting_hole_diameter / 2, t_slkp, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) else: if pck.mounting_hole_diameter > 0: addVLineWithKeepout(kicad_modt, l_mounth - pck.mounting_hole_diameter / 2, t_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_mounth + pck.mounting_hole_diameter / 2, t_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) for p in range(0, len(pads)): yl1 = t_slkp + h_slkp yl2 = pads[p][1] if yl2>yl1: addVLineWithKeepout(kicad_modt,pads[p][0], yl1, yl2, 'F.SilkS', lw_slk, keepouts) # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt+yshift)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt+yshift)], layer='F.CrtYd', width=lw_crt)) # create pads for p in range(0,len(pads)): if p==0: kicad_modt.append( Pad(number=p+1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=pads[p], size=padsize, drill=pck.drill, layers=['*.Cu', '*.Mask'])) else: kicad_modt.append( Pad(number=p+1, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=pads[p], size=padsize, drill=pck.drill, layers=['*.Cu', '*.Mask'])) # add model if (has3d): kicad_modt.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # horizontal symbols for rectangular transistors def makeHOR(lib_name, pck, has3d=False, x_3d=[0, 0, 0], s_3d=[1,1,1], lptext="_LargePads", r_3d=[0, 0, 0]): padsize = pck.pad l_fabp = -pck.pin_offset_x t_fabp = -pck.pin_minlength if pck.staggered_type >0: t_fabp=-pck.staggered_pin_minlength w_fabp = pck.plastic[0] h_fabp = pck.plastic[1] w_fabm = pck.metal[0] h_fabm = pck.metal[1] l_mounth = l_fabp + pck.mounting_hole_pos[0] t_mounth = t_fabp - pck.mounting_hole_pos[1] # calculate pad positions pads = [] yshift = 0 y1 = 0 y2 = 0 maxpiny = 0 if pck.staggered_type == 1: y1 = pck.staggered_rm[1] yshift = -pck.staggered_rm[1] y2 = 0 maxpiny = pck.staggered_rm[1] if len(pck.staggered_pad) > 0: padsize = pck.staggered_pad elif pck.staggered_type == 2: y1 = 0 yshift = 0 y2 = pck.staggered_rm[1] maxpiny = pck.staggered_rm[1] if len(pck.staggered_pad) > 0: padsize = pck.staggered_pad y=y1 x = 0 for p in range(1, pck.pins + 1): if (p % 2) == 1: y = y1 else: y = y2 pads.append([x, y]) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm pinwid = (pck.pins - 1) * pck.rm if len(pck.rm_list) > 0: pinwid = 0 for rm in pck.rm_list: pinwid = pinwid + rm l_slkp = l_fabp - slk_offset t_slkp = t_fabp + slk_offset w_slkp = w_fabp + 2 * slk_offset h_slkp = h_fabp + 2 * slk_offset w_slkm = w_fabm + 2 * slk_offset h_slkm = h_fabm + 2 * slk_offset addpad = 0 l_crt = min(-padsize[0] / 2, l_fabp) - crt_offset t_crt = t_fabp - max(h_fabp, h_fabm) - crt_offset h_crt = (-t_crt + maxpiny+padsize[1] / 2) + crt_offset if len(pck.additional_pin_pad_size) > 0: h_crt = h_crt + (pck.additional_pin_pad[1] + pck.additional_pin_pad_size[1] / 2 - h_fabm) t_crt = t_crt - (pck.additional_pin_pad[1] + pck.additional_pin_pad_size[1] / 2 - h_fabm) addpad = pck.additional_pin_pad_size[0] addpadx = l_fabp + pck.additional_pin_pad[0] addpady = t_fabp - pck.additional_pin_pad[1] w_crt = max(max(max(w_fabp, w_fabm), pinwid + padsize[0]), addpad) + 2 * crt_offset txt_x = l_slkp + max(w_slkp, w_slkm) / 2 txt_t = (t_slkp - max(h_slkm, h_slkp)) - txt_offset txt_b = maxpiny+padsize[1] / 2 + txt_offset if len(pck.additional_pin_pad_size) > 0: txt_t = txt_t - (pck.additional_pin_pad[1] + pck.additional_pin_pad_size[1] / 2 - h_fabm) tag_items = ["Horizontal", "RM {0}mm".format(pck.rm)] footprint_name = pck.name if len(pck.additional_pin_pad_size) > 0: footprint_name = footprint_name + "-1EP" for t in pck.more_packnames: footprint_name = footprint_name + "_" + t footprint_name = footprint_name + "_Horizontal_TabDown" for t in pck.fpnametags: footprint_name = footprint_name + "_" + t if pck.staggered_type>0: footprint_name = footprint_name + "_Py{0}mm".format(pck.staggered_rm[1],3) if pck.largepads: tag_items.append("large Pads") footprint_name = footprint_name + lptext print(footprint_name) description = pck.name tags = pck.name for t in tag_items: description = description + ", " + t tags = tags + " " + t for t in pck.tags: description = description + ", " + t tags = tags + " " + t if len(pck.webpage)>0: description = description + ", see " + pck.webpage # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modt = Translation(0, yshift) kicad_mod.append(kicad_modt) # set general values kicad_modt.append(Text(type='reference', text='REF**', at=[txt_x, txt_t], layer='F.SilkS')) kicad_modt.append(Text(type='user', text='%R', at=[txt_x, txt_t], layer='F.Fab')) kicad_modt.append(Text(type='value', text=footprint_name, at=[txt_x, txt_b], layer='F.Fab')) # create FAB-layer if (h_fabm > 0): if len(pck.plastic_angled)>0: if len(pck.metal_angled) > 0: addRectAngledTopNoBottom(kicad_modt, [l_fabp + pck.metal_offset_x, t_fabp - h_fabp+pck.plastic_angled[1]], [l_fabp + pck.metal_offset_x + w_fabm, t_fabp - h_fabm], pck.metal_angled, 'F.Fab', lw_fab) else: kicad_modt.append(RectLine(start=[l_fabp + pck.metal_offset_x, t_fabp - h_fabp-pck.plastic_angled[1]], end=[l_fabp + pck.metal_offset_x + w_fabm, t_fabp - h_fabm], layer='F.Fab', width=lw_fab)) else: if len(pck.metal_angled)>0: addRectAngledTop(kicad_modt, [l_fabp + pck.metal_offset_x, t_fabp - h_fabp], [l_fabp + pck.metal_offset_x + w_fabm, t_fabp - h_fabm], pck.metal_angled, 'F.Fab', lw_fab) else: kicad_modt.append(RectLine(start=[l_fabp + pck.metal_offset_x, t_fabp - h_fabp], end=[l_fabp + pck.metal_offset_x + w_fabm, t_fabp - h_fabm], layer='F.Fab', width=lw_fab)) if len(pck.plastic_angled)>0: addRectAngledTop(kicad_modt, [l_fabp, t_fabp], [l_fabp + w_fabp, t_fabp - h_fabp], pck.plastic_angled, 'F.Fab', lw_fab) else: kicad_modt.append( RectLine(start=[l_fabp, t_fabp], end=[l_fabp + w_fabp, t_fabp - h_fabp], layer='F.Fab', width=lw_fab)) if pck.mounting_hole_diameter > 0: kicad_modt.append( Circle(center=[l_mounth, t_mounth], radius=pck.mounting_hole_diameter / 2, layer='F.Fab', width=lw_fab)) for p in range(0, len(pads)): kicad_modt.append(Line(start=[pads[p][0], t_fabp], end=[pads[p][0], pads[p][1]], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer keepouts = [] for p in range(0,len(pads)): if p==0: keepouts=keepouts+addKeepoutRect(pads[p][0],pads[p][1],padsize[0]+2*slk_dist,padsize[1]+2*slk_dist) else: keepouts=keepouts+addKeepoutRound(pads[p][0],pads[p][1],padsize[0]+2*slk_dist,padsize[1]+2*slk_dist) if len(pck.additional_pin_pad_size) > 0: keepouts.append([addpadx - pck.additional_pin_pad_size[0] / 2 - slk_dist, addpadx + pck.additional_pin_pad_size[0] / 2 + slk_dist, addpady - pck.additional_pin_pad_size[1] / 2 - slk_dist, addpady + pck.additional_pin_pad_size[1] / 2 + slk_dist]) addHLineWithKeepout(kicad_modt, l_slkp, l_slkp + w_slkp, t_slkp, 'F.SilkS', lw_slk, keepouts) if h_fabm > 0: addHLineWithKeepout(kicad_modt, l_slkp, l_slkp + w_slkp, t_slkp - h_slkm, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_slkp, t_slkp, t_slkp - h_slkm, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_slkp + w_slkp, t_slkp, t_slkp - h_slkm, 'F.SilkS', lw_slk, keepouts) else: addHLineWithKeepout(kicad_modt, l_slkp, l_slkp + w_slkp, t_slkp - h_slkp, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_slkp, t_slkp, t_slkp - h_slkp, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modt, l_slkp + w_slkp, t_slkp, t_slkp - h_slkp, 'F.SilkS', lw_slk, keepouts) for p in range(0, len(pads)): addVLineWithKeepout(kicad_modt, pads[p][0], t_slkp, pads[p][1], 'F.SilkS', lw_slk, keepouts) # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt+yshift)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt+yshift)], layer='F.CrtYd', width=lw_crt)) # create mounting hole if pck.mounting_hole_drill > 0: kicad_modt.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_OVAL, at=[l_mounth, t_mounth], size=[pck.mounting_hole_drill, pck.mounting_hole_drill], drill=pck.mounting_hole_drill, layers=['*.Cu', '*.Mask'])) if len(pck.additional_pin_pad_size) > 0: kicad_modt.append(Pad(number=pck.pins + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[addpadx, addpady], size=pck.additional_pin_pad_size, drill=0, layers=['F.Cu', 'F.Mask', 'F.Paste'])) # create pads for p in range(0,len(pads)): if p==0: kicad_modt.append( Pad(number=p+1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=pads[p], size=padsize, drill=pck.drill, layers=['*.Cu', '*.Mask'])) else: kicad_modt.append( Pad(number=p+1, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=pads[p], size=padsize, drill=pck.drill, layers=['*.Cu', '*.Mask'])) # add model if (has3d): kicad_modt.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # vertical, mounted-from-Lowerside symbols for rectangular transistors def makeVERTLS(lib_name, pck, has3d=False, x_3d=[0, 0, 0], s_3d=[1,1,1], lptext="_LargePads", r_3d=[0, 0, 0]): l_fabp = -pck.pin_offset_x t_fabp = -pck.pin_offset_z w_fabp = pck.plastic[0] h_fabp = pck.plastic[2] w_fabm = pck.metal[0] h_fabm = pck.metal[2] pinwid=(pck.pins - 1) * pck.rm if len(pck.rm_list)>0: pinwid=0 for rm in pck.rm_list: pinwid=pinwid+rm l_slkp = l_fabp - slk_offset t_slkp = t_fabp - slk_offset w_slkp = w_fabp + 2 * slk_offset h_slkp = h_fabp + 2 * slk_offset w_slkm = w_fabm + 2 * slk_offset h_slkm = h_fabm + 2 * slk_offset l_crt = min(-pck.pad[0] / 2, l_fabp) - crt_offset t_crt = min(-pck.pad[1] / 2, t_fabp) - crt_offset w_crt = max(max(w_fabp, w_fabm), pinwid + pck.pad[0]) + 2 * crt_offset h_crt = max(t_fabp+max(h_fabp, h_fabm) + crt_offset-t_crt, -t_crt + pck.pad[1] / 2+crt_offset) l_mounth = l_fabp + pck.mounting_hole_pos[0] txt_x = l_slkp + max(w_slkp, w_slkm) / 2 tag_items = ["Vertical", "RM {0}mm".format(pck.rm), "mount on lower-side of PCB"] footprint_name = pck.name for t in pck.more_packnames: footprint_name = footprint_name + "_" + t footprint_name = footprint_name + "_Vertical" for t in pck.fpnametags: footprint_name = footprint_name + "_" + t footprint_name = footprint_name + "_MountFromLS" if pck.largepads: tag_items.append("large Pads") footprint_name = footprint_name + lptext print(footprint_name) description = pck.name tags = pck.name for t in tag_items: description = description + ", " + t tags = tags + " " + t for t in pck.tags: description = description + ", " + t tags = tags + " " + t if len(pck.webpage)>0: description = description + ", see " + pck.webpage # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modt = Translation(-pinwid, 0) kicad_mod.append(kicad_modt) # set general values kicad_modt.append(Text(type='reference', text='REF**', at=[txt_x, t_slkp - txt_offset], layer='F.SilkS')) kicad_modt.append(Text(type='user', text='%R', at=[txt_x, t_slkp - txt_offset], layer='B.Fab')) kicad_modt.append( Text(type='value', text=footprint_name, at=[txt_x, t_slkp + max(h_slkm, h_slkp) + txt_offset], layer='B.Fab')) # create FAB-layer kicad_modt.append( RectLine(start=[l_fabp, t_fabp], end=[l_fabp + w_fabp, t_fabp + h_fabp], layer='B.Fab', width=lw_fab)) if (pck.metal[2] > 0): kicad_modt.append( Line(start=[l_fabp, t_fabp + h_fabm], end=[l_fabp + w_fabp, t_fabp + h_fabm], layer='B.Fab', width=lw_fab)) if pck.mounting_hole_diameter > 0: kicad_modt.append(Line(start=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp + h_fabm], layer='B.Fab', width=lw_fab)) kicad_modt.append(Line(start=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp + h_fabm], layer='B.Fab', width=lw_fab)) else: if pck.mounting_hole_diameter > 0: kicad_modt.append(Line(start=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth - pck.mounting_hole_diameter / 2, t_fabp + h_fabp], layer='B.Fab', width=lw_fab)) kicad_modt.append(Line(start=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp], end=[l_mounth + pck.mounting_hole_diameter / 2, t_fabp + h_fabp], layer='B.Fab', width=lw_fab)) # create SILKSCREEN-layer keepouts = [] x = pinwid for p in range(1, pck.pins + 1): if p == 1: keepouts = keepouts + addKeepoutRect(x, 0, pck.pad[0] + 2 * slk_dist, pck.pad[1] + 2 * slk_dist) else: keepouts = keepouts + addKeepoutRound(x, 0, pck.pad[0] + 2 * slk_dist, pck.pad[1] + 2 * slk_dist) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x - pck.rm_list[p-1] else: x = x - pck.rm #for ko in keepouts: # kicad_modt.append( # RectLine(start=[ko[0], ko[2]], # end=[ko[1], ko[3]], # layer='F.CrtYd', width=0.01)) addHDLineWithKeepout(kicad_modt, l_slkp, 3 * lw_slk, l_slkp + w_slkp, t_slkp, 'F.SilkS', lw_slk, keepouts) addHDLineWithKeepout(kicad_modt, l_slkp, 3 * lw_slk, l_slkp + w_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_slkp, t_slkp, 3 * lw_slk, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_slkp + w_slkp, t_slkp, 3 * lw_slk, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) if (pck.metal[2] > 0): addHDLineWithKeepout(kicad_modt, l_slkp, 3 * lw_slk, l_slkp + w_slkp, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) if pck.mounting_hole_diameter > 0: addVDLineWithKeepout(kicad_modt, l_mounth - pck.mounting_hole_diameter / 2, t_slkp, 3 * lw_slk, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_mounth + pck.mounting_hole_diameter / 2, t_slkp, 3 * lw_slk, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) else: if pck.mounting_hole_diameter > 0: addVDLineWithKeepout(kicad_modt, l_mounth - pck.mounting_hole_diameter / 2, t_slkp, 3 * lw_slk, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_mounth + pck.mounting_hole_diameter / 2, t_slkp, 3 * lw_slk, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt-pinwid), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt-pinwid), roundCrt(t_crt + h_crt)], layer='B.CrtYd', width=lw_crt)) # create pads x = pinwid for p in range(1, pck.pins + 1): if (p == 1): kicad_modt.append( Pad(number=p, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[x, 0], size=pck.pad, drill=pck.drill, layers=['*.Cu', '*.Mask'])) else: kicad_modt.append( Pad(number=p, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[x, 0], size=pck.pad, drill=pck.drill, layers=['*.Cu', '*.Mask'])) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x - pck.rm_list[p-1] else: x = x - pck.rm # add model if (has3d): kicad_modt.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # horizontal, mounted-from-Lowerside symbols for rectangular transistors def makeHORLS(lib_name, pck, has3d=False, x_3d=[0, 0, 0], s_3d=[1,1,1], lptext="_LargePads", r_3d=[0, 0, 0]): l_fabp = -pck.pin_offset_x t_fabp = -pck.pin_minlength w_fabp = pck.plastic[0] h_fabp = pck.plastic[1] w_fabm = pck.metal[0] h_fabm = pck.metal[1] l_slkp = l_fabp - slk_offset t_slkp = t_fabp + slk_offset w_slkp = w_fabp + 2 * slk_offset h_slkp = h_fabp + 2 * slk_offset w_slkm = w_fabm + 2 * slk_offset h_slkm = h_fabm + 2 * slk_offset pinwid = (pck.pins - 1) * pck.rm if len(pck.rm_list) > 0: pinwid = 0 for rm in pck.rm_list: pinwid = pinwid + rm l_crt = min(-pck.pad[0] / 2, l_fabp) - crt_offset t_crt = t_fabp - max(h_fabp, h_fabm) - crt_offset h_crt = (-t_crt + pck.pad[1] / 2) + crt_offset addpad = 0 if len(pck.additional_pin_pad_size) > 0: h_crt = h_crt + (pck.additional_pin_pad[1] + pck.additional_pin_pad_size[1] / 2 - h_fabm) t_crt = t_crt - (pck.additional_pin_pad[1] + pck.additional_pin_pad_size[1] / 2 - h_fabm) addpad = pck.additional_pin_pad_size[0] addpadx = l_fabp + pck.additional_pin_pad[0] addpady = t_fabp - pck.additional_pin_pad[1] w_crt = max(max(max(w_fabp, w_fabm), pinwid + pck.pad[0]), addpad) + 2 * crt_offset l_mounth = l_fabp + pck.mounting_hole_pos[0] t_mounth = t_fabp - pck.mounting_hole_pos[1] txt_x = l_slkp + max(w_slkp, w_slkm) / 2 txt_t = (t_slkp - max(h_slkm, h_slkp)) - txt_offset txt_b = pck.pad[1] / 2 + txt_offset if len(pck.additional_pin_pad_size) > 0: txt_t = txt_t - (pck.additional_pin_pad[1] + pck.additional_pin_pad_size[1] / 2 - h_fabm) tag_items = ["Horizontal", "RM {0}mm".format(pck.rm), "mount on lower-side of PCB", "mount with cooling pad pointing away from PCB", "Reversed"] footprint_name = pck.name if len(pck.additional_pin_pad_size) > 0: footprint_name = footprint_name + "-1EP" for t in pck.more_packnames: footprint_name = footprint_name + "_" + t footprint_name = footprint_name + "_Horizontal" for t in pck.fpnametags: footprint_name = footprint_name + "_" + t footprint_name = footprint_name + "_TabUp_MountFromLS" if pck.largepads: tag_items.append("large Pads") footprint_name = footprint_name + lptext print(footprint_name) description = pck.name tags = pck.name for t in tag_items: description = description + ", " + t tags = tags + " " + t for t in pck.tags: description = description + ", " + t tags = tags + " " + t if len(pck.webpage)>0: description = description + ", see " + pck.webpage # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modt=Translation(0,0)#-(pck.pins - 1) * pck.rm,0) kicad_mod.append(kicad_modt) # set general values kicad_modt.append(Text(type='reference', text='REF**', at=[txt_x, txt_t], layer='F.SilkS')) kicad_modt.append(Text(type='user', text='%R', at=[txt_x, txt_t], layer='B.Fab')) kicad_modt.append(Text(type='value', text=footprint_name, at=[txt_x, txt_b], layer='B.Fab')) # create FAB-layer if (h_fabm > 0): if len(pck.metal_angled) > 0: addRectAngledTop(kicad_modt, [l_fabp + pck.metal_offset_x, t_fabp - h_fabp], [l_fabp + pck.metal_offset_x + w_fabm, t_fabp - h_fabm], pck.metal_angled, 'B.Fab', lw_fab) else: kicad_modt.append(RectLine(start=[l_fabp + pck.metal_offset_x, t_fabp - h_fabp], end=[l_fabp + pck.metal_offset_x + w_fabm, t_fabp - h_fabm], layer='B.Fab', width=lw_fab)) if len(pck.plastic_angled) > 0: addRectAngledTop(kicad_modt, [l_fabp, t_fabp], [l_fabp + w_fabp, t_fabp - h_fabp], pck.plastic_angled, 'B.Fab', lw_fab) else: kicad_modt.append( RectLine(start=[l_fabp, t_fabp], end=[l_fabp + w_fabp, t_fabp - h_fabp], layer='B.Fab', width=lw_fab)) # if (h_fabm > 0): # kicad_modt.append(RectLine(start=[l_fabp + pck.metal_offset_x, t_fabp - h_fabp], # end=[l_fabp + pck.metal_offset_x + w_fabm, t_fabp - h_fabm], layer='B.Fab', # width=lw_fab)) # kicad_modt.append( # RectLine(start=[l_fabp, t_fabp], end=[l_fabp + w_fabp, t_fabp - h_fabp], layer='B.Fab', width=lw_fab)) # kicad_modt.append( # RectLine(start=[l_fabp, t_fabp], end=[l_fabp + w_fabp, t_fabp - h_fabp], layer='B.Fab', width=lw_fab)) if pck.mounting_hole_diameter > 0: kicad_modt.append( Circle(center=[l_mounth, t_mounth], radius=pck.mounting_hole_diameter / 2, layer='B.Fab', width=lw_fab)) x = 0 for p in range(1, pck.pins + 1): kicad_modt.append(Line(start=[x, t_fabp], end=[x, 0], layer='B.Fab', width=lw_fab)) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm # create SILKSCREEN-layer keepouts = [] x = 0 for p in range(1, pck.pins + 1): if p == 1: keepouts = keepouts + addKeepoutRect(x, 0, pck.pad[0] + 2 * slk_dist, pck.pad[1] + 2 * slk_dist) else: keepouts = keepouts + addKeepoutRound(x, 0, pck.pad[0] + 2 * slk_dist, pck.pad[1] + 2 * slk_dist) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm if len(pck.additional_pin_pad_size) > 0: keepouts.append([addpadx - pck.additional_pin_pad_size[0] / 2 - slk_dist, addpadx + pck.additional_pin_pad_size[0] / 2 + slk_dist, addpady - pck.additional_pin_pad_size[1] / 2 - slk_dist, addpady + pck.additional_pin_pad_size[1] / 2 + slk_dist]) addHDLineWithKeepout(kicad_modt, l_slkp, 3 * lw_slk, l_slkp + w_slkp, t_slkp, 'F.SilkS', lw_slk, keepouts) if h_fabm > 0: addHDLineWithKeepout(kicad_modt, l_slkp, 3 * lw_slk, l_slkp + w_slkp, t_slkp - h_slkm, 'F.SilkS', lw_slk, keepouts) addHDLineWithKeepout(kicad_modt, l_slkp, 3 * lw_slk, l_slkp + w_slkp, t_fabp - h_fabp, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_slkp, t_slkp, 3 * lw_slk, t_slkp - h_slkm, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_slkp + w_slkp, t_slkp, 3 * lw_slk, t_slkp - h_slkm, 'F.SilkS', lw_slk, keepouts) else: addHDLineWithKeepout(kicad_modt, l_slkp, 3 * lw_slk, l_slkp + w_slkp, t_slkp - h_slkp, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_slkp, t_slkp, 3 * lw_slk, t_slkp - h_slkp, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_modt, l_slkp + w_slkp, t_slkp, 3 * lw_slk, t_slkp - h_slkp, 'F.SilkS', lw_slk, keepouts) x = 0 for p in range(1, pck.pins + 1): addVDLineWithKeepout(kicad_modt, x, t_slkp, 3 * lw_slk, -(pck.pad[1]/2+slk_dist), 'F.SilkS', lw_slk, keepouts) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm # create courtyard kicad_modt.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt)], layer='B.CrtYd', width=lw_crt)) # create mounting hole if pck.mounting_hole_drill > 0: kicad_modt.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_OVAL, at=[l_mounth, t_mounth], size=[pck.mounting_hole_drill, pck.mounting_hole_drill], drill=pck.mounting_hole_drill, layers=['*.Cu', '*.Mask'])) if len(pck.additional_pin_pad_size) > 0: kicad_modt.append(Pad(number=pck.pins + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[addpadx, addpady], size=pck.additional_pin_pad_size, drill=0, layers=['B.Cu', 'F.Mask', 'B.Paste'])) # create pads x = 0 for p in range(1, pck.pins + 1): if (p == 1): kicad_modt.append( Pad(number=p, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[x, 0], size=pck.pad, drill=pck.drill, layers=['*.Cu', '*.Mask'])) else: kicad_modt.append( Pad(number=p, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[x, 0], size=pck.pad, drill=pck.drill, layers=['*.Cu', '*.Mask'])) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm # add model if (has3d): kicad_modt.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # horizontal reversed symbols for rectangular transistors def makeHORREV(lib_name, pck, has3d=False, x_3d=[0, 0, 0], s_3d=[1 ,1,1], lptext="_LargePads", r_3d=[0, 0, 0]): l_fabp = -pck.pin_offset_x t_fabp = pck.pin_minlength w_fabp = pck.plastic[0] h_fabp = pck.plastic[1] w_fabm = pck.metal[0] h_fabm = pck.metal[1] l_slkp = l_fabp - slk_offset t_slkp = t_fabp - slk_offset w_slkp = w_fabp + 2 * slk_offset h_slkp = h_fabp + 2 * slk_offset w_slkm = w_fabm + 2 * slk_offset h_slkm = h_fabm + 2 * slk_offset pinwid = (pck.pins - 1) * pck.rm if len(pck.rm_list) > 0: pinwid = 0 for rm in pck.rm_list: pinwid = pinwid + rm l_crt = min(-pck.pad[0] / 2, l_fabp) - crt_offset t_crt = -pck.pad[1]/2- crt_offset w_crt = max(max(w_fabp, w_fabm), pinwid + pck.pad[0]) + 2 * crt_offset h_crt = -t_crt + t_fabp+max(h_fabp, h_fabm) + crt_offset l_mounth = l_fabp + pck.mounting_hole_pos[0] t_mounth = t_fabp + pck.mounting_hole_pos[1] txt_x = l_slkp + max(w_slkp, w_slkm) / 2 txt_t = (t_slkp + max(h_slkm, h_slkp)) + txt_offset txt_b = -pck.pad[1] / 2 - txt_offset tag_items = ["Horizontal", "RM {0}mm".format(pck.rm)] footprint_name = pck.name for t in pck.more_packnames: footprint_name = footprint_name + "_" + t footprint_name = footprint_name + "_Horizontal" + "_TabUp" for t in pck.fpnametags: footprint_name = footprint_name + "_" + t if pck.largepads: tag_items.append("large Pads") footprint_name = footprint_name + lptext print(footprint_name) description = pck.name tags = pck.name for t in tag_items: description = description + ", " + t tags = tags + " " + t for t in pck.tags: description = description + ", " + t tags = tags + " " + t if len(pck.webpage)>0: description = description + ", see " + pck.webpage # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[txt_x, txt_t], layer='F.SilkS')) kicad_mod.append(Text(type='user', text='%R', at=[txt_x, txt_t], layer='F.Fab')) kicad_mod.append(Text(type='value', text=footprint_name, at=[txt_x, txt_b], layer='F.Fab')) if (h_fabm > 0): if len(pck.metal_angled) > 0: addRectAngledBottom(kicad_mod, [l_fabp + pck.metal_offset_x, t_fabp + h_fabp], [l_fabp + pck.metal_offset_x + w_fabm, t_fabp + h_fabm], pck.metal_angled, 'F.Fab', lw_fab) else: kicad_mod.append(RectLine(start=[l_fabp + pck.metal_offset_x, t_fabp + h_fabp], end=[l_fabp + pck.metal_offset_x + w_fabm, t_fabp + h_fabm], layer='F.Fab', width=lw_fab)) if len(pck.plastic_angled) > 0: addRectAngledBottom(kicad_mod, [l_fabp, t_fabp], [l_fabp + w_fabp, t_fabp + h_fabp], pck.plastic_angled, 'F.Fab', lw_fab) else: kicad_mod.append( RectLine(start=[l_fabp, t_fabp], end=[l_fabp + w_fabp, t_fabp + h_fabp], layer='F.Fab', width=lw_fab)) if pck.mounting_hole_diameter > 0: kicad_mod.append(Circle(center=[l_mounth, t_mounth], radius=pck.mounting_hole_diameter / 2, layer='F.Fab', width=lw_fab)) x = 0 for p in range(1, pck.pins + 1): kicad_mod.append(Line(start=[x, t_fabp], end=[x, 0], layer='F.Fab', width=lw_fab)) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm # create SILKSCREEN-layer keepouts = [] x = 0 for p in range(1, pck.pins + 1): if p==1: keepouts=keepouts+addKeepoutRect(x,0,pck.pad[0]+2*slk_dist,pck.pad[1]+2*slk_dist) else: keepouts=keepouts+addKeepoutRound(x,0,pck.pad[0]+2*slk_dist,pck.pad[1]+2*slk_dist) x = x + pck.rm addHLineWithKeepout(kicad_mod, l_slkp, l_slkp + w_slkp, t_slkp, 'F.SilkS', lw_slk, keepouts) addHLineWithKeepout(kicad_mod, l_slkp, l_slkp + w_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_mod, l_slkp, t_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_mod, l_slkp + w_slkp, t_slkp, t_slkp + h_slkp, 'F.SilkS', lw_slk, keepouts) if (h_fabm > 0): addHDLineWithKeepout(kicad_mod, l_slkp + pck.metal_offset_x, 10*lw_slk, l_slkp + pck.metal_offset_x + w_slkm, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_mod, l_slkp + pck.metal_offset_x, t_slkp + h_slkp+lw_slk*2, 10 * lw_slk, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) addVDLineWithKeepout(kicad_mod, l_slkp + pck.metal_offset_x + w_slkm, t_slkp + h_slkp+lw_slk*2, 10 * lw_slk, t_slkp + h_slkm, 'F.SilkS', lw_slk, keepouts) x = 0 for p in range(1, pck.pins + 1): addVLineWithKeepout(kicad_mod, x, t_slkp, pck.pad[1]/2+slk_dist, 'F.SilkS', lw_slk, keepouts) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt)], layer='F.CrtYd', width=lw_crt)) # create mounting hole if pck.mounting_hole_drill > 0: kicad_mod.append(Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_OVAL, at=[l_mounth, t_mounth], size=[pck.mounting_hole_drill, pck.mounting_hole_drill], drill=pck.mounting_hole_drill, layers=['*.Cu', '*.Mask'])) # create pads x = 0 for p in range(1, pck.pins + 1): if (p==1): kicad_mod.append(Pad(number=p, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[x, 0], size=pck.pad, drill=pck.drill, layers=['*.Cu', '*.Mask'])) else: kicad_mod.append(Pad(number=p, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[x, 0], size=pck.pad, drill=pck.drill,layers=['*.Cu', '*.Mask'])) if len(pck.rm_list)>0 and p<=len(pck.rm_list): x = x + pck.rm_list[p-1] else: x = x + pck.rm # add model if (has3d): kicad_mod.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # horizontal symbols for rectangular transistors def makeTORound(lib_name, pck, has3d=False, x_3d=[0, 0, 0], s_3d=[1,1,1], lptext="_LargePads"): padsize = pck.pad d_fab=pck.diameter_outer d_slk=pck.diameter_outer+2*slk_offset # calculate pad positions pads = [] yshift = 0 xshift = 0 a=pck.pin1_angle firstPin=True for p in range(1, pck.pins + 1): x=pck.pin_circle_diameter/2*math.cos(a/180*math.pi) y=pck.pin_circle_diameter/2*math.sin(a/180*math.pi) a = a + pck.pin_dangle if (len(pck.used_pins)<=0) or ((p-1) in pck.used_pins): pads.append([x, y]) if firstPin: xshift=-x yshift=-y firstPin=False txt_t = -d_slk/2 - txt_offset txt_b = d_slk/2 + txt_offset tag_items = [] footprint_name = pck.name for t in pck.more_packnames: footprint_name = footprint_name + "_" + t for t in pck.fpnametags: footprint_name = footprint_name + "_" + t if pck.largepads: tag_items.append("large Pads") footprint_name = footprint_name + lptext print(footprint_name) description = pck.name tags = pck.name for t in tag_items: description = description + ", " + t tags = tags + " " + t for t in pck.tags: description = description + ", " + t tags = tags + " " + t if len(pck.webpage)>0: description = description + ", see " + pck.webpage # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modt = Translation(xshift, yshift) kicad_mod.append(kicad_modt) # set general values kicad_modt.append(Text(type='reference', text='REF**', at=[0, txt_t], layer='F.SilkS')) kicad_modt.append(Text(type='user', text='%R', at=[0, txt_t], layer='F.Fab')) kicad_modt.append(Text(type='value', text=footprint_name, at=[0, txt_b], layer='F.Fab')) # create FAB-layer kicad_modt.append(Circle(center=[0, 0], radius=pck.diameter_inner / 2, layer='F.Fab', width=lw_fab)) if pck.mark_width > 0 and pck.mark_len > 0: a=pck.mark_angle da=math.asin(pck.mark_width/d_fab)/math.pi*180 a1=a+da a2=a-da x1 = [(pck.diameter_outer / 2) * math.cos(a1 / 180 * math.pi), (pck.diameter_outer / 2) * math.sin(a1 / 180 * math.pi)] x3 = [(pck.diameter_outer / 2) * math.cos(a2 / 180 * math.pi), (pck.diameter_outer / 2) * math.sin(a2 / 180 * math.pi)] dx1= (pck.mark_len) * math.cos(a / 180 * math.pi) dx2 = (pck.mark_len) * math.sin(a / 180 * math.pi) x2 = [x1[0] + dx1, x1[1] + dx2] x4 = [x3[0] + dx1, x3[1] + dx2] minx=min(x2[0],x4[0]) miny=min(x2[1],x4[1]) kicad_modt.append(Arc(center=[0, 0], start=x1, angle=(360-2*da), layer='F.Fab', width=lw_fab)) kicad_modt.append(Line(start=x1, end=x2, angle=0, layer='F.Fab', width=lw_fab)) kicad_modt.append(Line(start=x2, end=x4, angle=0, layer='F.Fab', width=lw_fab)) kicad_modt.append(Line(start=x4, end=x3, angle=0, layer='F.Fab', width=lw_fab)) else: kicad_modt.append(Circle(center=[0, 0], radius=pck.diameter_outer / 2, layer='F.Fab', width=lw_fab)) if pck.window_diameter>0: addCircleLF(kicad_modt, [0,0], pck.window_diameter/2, 'F.Fab', lw_fab, 4*lw_fab) # create SILKSCREEN-layer if pck.mark_width>0 and pck.mark_len>0: a=pck.mark_angle da=math.asin((pck.mark_width+2*slk_offset)/d_slk)/math.pi*180 a1=a+da a2=a-da x1 = [(d_slk / 2) * math.cos(a1 / 180 * math.pi), (d_slk / 2) * math.sin(a1 / 180 * math.pi)] x3 = [(d_slk / 2) * math.cos(a2 / 180 * math.pi), (d_slk / 2) * math.sin(a2 / 180 * math.pi)] dx1= (pck.mark_len+slk_offset) * math.cos(a / 180 * math.pi) dx2 = (pck.mark_len+slk_offset) * math.sin(a / 180 * math.pi) x2 = [x1[0] + dx1, x1[1] + dx2] x4 = [x3[0] + dx1, x3[1] + dx2] #minx=min(x2[0],x4[0]) #miny=min(x2[1],x4[1]) kicad_modt.append(Arc(center=[0, 0], start=x1, angle=(360-2*da), layer='F.SilkS', width=lw_slk)) kicad_modt.append(Line(start=x1, end=x2, angle=0, layer='F.SilkS', width=lw_slk)) kicad_modt.append(Line(start=x2, end=x4, angle=0, layer='F.SilkS', width=lw_slk)) kicad_modt.append(Line(start=x4, end=x3, angle=0, layer='F.SilkS', width=lw_slk)) else: kicad_modt.append(Circle(center=[0, 0], radius=d_slk/2, layer='F.SilkS', width=lw_slk)) if pck.mark_width > 0 and pck.mark_len > 0: kicad_mod.append( RectLine(start=[roundCrt(xshift+min(minx-crt_offset,-d_fab/2-crt_offset)), roundCrt(yshift+min(miny-crt_offset,-d_fab/2-crt_offset))], end=[roundCrt(xshift+d_fab/2+crt_offset), roundCrt(yshift+d_fab/2+crt_offset)], layer='F.CrtYd', width=lw_crt)) else: kicad_mod.append(Circle(center=[roundCrt(xshift), roundCrt(yshift)], radius=roundCrt(d_fab / 2+crt_offset), layer='F.CrtYd', width=lw_crt)) # create pads for p in range(0, len(pads)): if p == 0: kicad_modt.append( Pad(number=p + 1, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=pads[p], size=[roundG(padsize[0]*1.3,0.1),padsize[1]], drill=pck.drill, layers=['*.Cu', '*.Mask'])) else: kicad_modt.append( Pad(number=p + 1, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=pads[p], size=padsize, drill=pck.drill, layers=['*.Cu', '*.Mask'])) # add model if (has3d): kicad_modt.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=[0, 0, 0])) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') if __name__ == '__main__': # make standard packages packs = ["TO-264", "TO-247", "TO-218", "TO-251", "TO-126", "TO-220", "TO-3P", "TO-262", "SIPAK","TO-3PB", "TO-220F"] pins = [[2, 3,5], [2, 3,4,5], [2, 3], [2, 3], [2, 3], [2, 3, 4,5], [3], [3,5], [3], [3], [2, 3, 4, 5, ]] rms = [ [0, 0,3.81], [0, 0,2.54,2.54], [0, 0], [0, 0], [0, 0], [0, 0, 2.54,1.7], [0], [0,1.7], [0], [0], [0, 0, 2.54,1.7]] #makeVERTLS("${KISYS3DMOD}/Package_TO_SOT_THT", pack("SOT93", 2, 0, 0, False),False, [0, 0, 0], [0, 0, 0]) #exit() for p in range(0, len(packs)): for pidx in range(0, len(pins[p])): o3d = [0, 0, 0] o3dh = [0, 0, 0] o3dls = [0, 0, 0] o3dvls = [0, 0, 0] s3d = [1,1,1] r3d=[0,0,0] r3dr=r3d pack_norm = pack(packs[p], pins[p][pidx], rms[p][pidx], 0, False) libn = "${KISYS3DMOD}/Package_TO_SOT_THT" makeVERT(libn, pack_norm, True, o3d, s3d, "_LargePads", r3d) #makeVERTLS(libn, pack_norm, True, o3dvls, s3d, "_LargePads", r3d) makeHOR(libn, pack_norm, True, o3dh, s3d, "_LargePads", r3d) if (len(pack_norm.additional_pin_pad) <= 0): #makeHORLS(libn, pack_norm, True, o3dls, s3d, "_LargePads", r3d) makeHORREV(libn, pack_norm, True, o3d, s3d, "_LargePads", r3dr) # make staggered packages packs = [ "TO-220", "TO-220F", ] pins = [ [4, 5, 7, 9, 11, 15, ], [ 4, 4, 5, 5, 7, 9, 11, 15 ], ] rms = [ [2.54, 1.7, 1.27, 0.97, 1.7, 1.27, ], [ 2.54, 2.54, 1.7, 1.7, 1.27, 0.9, 1.7, 1.27 ], ] pitchys = [ [], [ 0, 2.05, 0, 2.06, 0, 0, 0, 0 ], ] ypinoffsets = [ [], [ 0, 0, 0, 4.5, 0, 0, 0, 0 ], ] for p in range(0, len(packs)): for pidx in range(0, len(pins[p])): o3d = [0, 0, 0] s3d = [1,1,1] pitchy=0 if p4: self.pin_dangle = -360/pins self.mark_angle = self.pin1_angle + 45 # angular position of marking self.name = name self.webpage=""; if (name == "TO-18") or (name=="TO-46") or (name=="TO-52") or (name=="TO-72"): self.diameter_inner = 4.8 # diameter of top can self.diameter_outer = 5.8 # diameter of bottom can self.mark_width = 1.16 # width of marking self.mark_len = 1.17 # length of marking self.pin_circle_diameter = 2.54 # pin circle diameterdistance self.pad = [1.2,1.2] # width/height of pads self.drill = 0.7 # diameter of pad drills self.name = self.name + "-{0}".format(pins) # name of package if len(modifier)>0: self.name = self.name +"_"+modifier self.tags.append(modifier) if largepads: self.pad = [1.5, 1.5] # width/height of pads if (modifier=="Window") or (modifier=="Lens"): self.window_diameter = 4 # diameter of an on-top glass window if (name == "TO-5") or (name == "TO-5_PD5.08") or (name == "TO-11") or (name == "TO-12") or (name == "TO-33") or (name == "TO-39") or (name == "TO-99") or (name == "TO-78") or (name == "TO-100") or (name == "TO-75"): self.diameter_inner = 8.5 # diameter of top can self.diameter_outer = 9.4 # diameter of bottom can self.mark_width = 0.86 # width of marking self.mark_len = 1.14 # length of marking self.pin_circle_diameter = 5.08 # pin circle diameterdistance if (pins==6): self.pins=8 self.pin_dangle = -360 / self.pins self.used_pins=[0,1,2,4,5,6] elif (pins>6) and (name != "TO-5_PD5.08"): self.pin_circle_diameter = 5.84 # pin circle diameterdistance elif pins>8: self.mark_angle = self.pin1_angle + 36 # angular position of marking if (name == "TO-100"): self.pin_circle_diameter = 5.84 # pin circle diameterdistance self.pad = [1.2, 1.2] # width/height of pads self.drill = 0.7 # diameter of pad drills if (name == "TO-5_PD5.08"): self.name = "TO-5" + "-{0}_PD5.08".format(pins) # name of package else: self.name = self.name + "-{0}".format(pins) # name of package if len(modifier) > 0: self.name = self.name + "_" + modifier self.tags.append(modifier) if largepads: self.pad = [1.5, 1.5] # width/height of pads if (modifier == "Window") or (modifier == "Lens"): self.window_diameter = 5.9 # diameter of an on-top glass window if (name == "TO-8"): self.diameter_inner = 13.2 # diameter of top can self.diameter_outer = 14.4 # diameter of bottom can self.mark_width = 0.0 # width of marking self.mark_len = 0 # length of marking self.pin_circle_diameter = 7.1 # pin circle diameterdistance self.pad = [1.6, 1.6] # width/height of pads self.drill = 1.1 # diameter of pad drills self.name = self.name + "-{0}".format(pins) # name of package if len(modifier) > 0: self.name = self.name + "_" + modifier self.tags.append(modifier) if largepads: self.pad = [2, 2] # width/height of pads if (modifier == "Window") or (modifier == "Lens"): self.window_diameter = 0.43*25.4 # diameter of an on-top glass window if (name == "TO-17"): self.diameter_inner = 4.2 # diameter of top can self.diameter_outer = 5.2 # diameter of bottom can self.mark_width = 0.76 # width of marking self.mark_len = 0.75 # length of marking self.pin_circle_diameter = 1.8 # pin circle diameterdistance self.pad = [0.9,0.9] # width/height of pads self.drill = 0.6 # diameter of pad drills self.name = self.name + "-{0}".format(pins) # name of package if len(modifier) > 0: self.name = self.name + "_" + modifier self.tags.append(modifier) if largepads: self.pad = [1.3, 1.3] # width/height of pads if (modifier == "Window") or (modifier == "Lens"): self.window_diameter = 3.5 # diameter of an on-top glass window if (name == "TO-38"): self.diameter_inner = 12.3 # diameter of top can self.diameter_outer = 17.3 # diameter of bottom can self.mark_width = 0.0 # width of marking self.mark_len = 0.0 # length of marking self.pin_circle_diameter = 5.08 # pin circle diameterdistance self.pad = [1.3, 1.3] # width/height of pads self.drill = 0.8 # diameter of pad drills self.name = self.name + "-{0}".format(pins) # name of package if len(modifier) > 0: self.name = self.name + "_" + modifier self.tags.append(modifier) if largepads: self.pad = [1.6, 1.6] # width/height of pads if (modifier == "Window") or (modifier == "Lens"): self.window_diameter = 8 # diameter of an on-top glass window class pack: # metal_/plastic_ ^ # <--------width------> | # +-------------------+ ^ y # | | | x----> # | OO | mounting drill | # | | | # | METAL | | # +-------------------+ ^ metal_height # | | | | # | | | | # | PLASTIC | plastic_height | # | | | | # | | | | # | | | | # 0-------------------+ v 0= ref pos v # | | | ^ # | | | | # | | | pin_minlength # | | | | # | | | v # PPP PPP PPP PADs # <--rm--> # <-> # pin_offset_x # # 0-------------------+ 0= ref pos ^ ^ z # | METAL | metal_depth | | # +-------------------+ ^ v pin_offset_z | # | PLASTIC | plastic_depth | v # | PPP PPP PPP | | v # +-------------------+ v # def __init__(self): self.plastic = [0, 0, 0] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [0, 0, 0] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self. metal_offset_x =0 # offset of metal from left self.pins = 0 # number of pins self.rm = 0 # pin distance self.pad = [0, 0] # width/height of pads self.drill = 0 # diameter of pad drills self.name = "" # name of package self.mounting_hole_pos = [0, 0] # position of mounting hole from bottom-left self.mounting_hole_diameter = 0 # diameter of mounting hole in package self.mounting_hole_drill = 0 # diameter of mounting hole drill self.pin_minlength = 0 # min. elongation of pins before 90° bend self.pinw = [0, 0]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_x = 0 self.pin_offset_z = 0 self.largepads =False self.fpnametags =[] self.additional_pin_pad =[] # Position des Zusatz-SMD-Pads self.additional_pin_pad_size = [] # Größe des Zusatz-SMD-Pads self.plastic_angled=[] self.metal_angled = [] self.staggered_type=0 # 0=no staggering, 1=type1-staggering (pin1=fron), 2=type2-staggering (pin1=back) self.staggered_rm=[5.08,5.08] # y-distance between pins [vertical, horizontal] self.staggered_pin_offset_z = 0 # z-offset of back-pins in staggered mode [vertical, horizontal] self.staggered_pin_minlength = 0 # y-offset of back-pins in staggered mode self.staggered_pad=[] # pad size in staggered mode self.rm_list = [] self.more_packnames = [] # additional package names, e.g. "I2PAK" for TO-262 self.webpage=""; def __init__(self ,name ,pins=3 ,rm=0, staggered_type=0,largepads=False,pitchy=0,ypinoffset=0): self. additional_pin_pad =[] # Position des Zusatz-SMD-Pads self.additional_pin_pad_size = [] # Größe des Zusatz-SMD-Pads self.largepads =largepads self.fpnametags = [] self.metal_offset_x = 0 # offset of metal from left self.plastic_angled = [] self.metal_angled = [] self.staggered_type=staggered_type self.staggering_rm=[5.08,2.54] # y-distance between pins self.staggered_pin_offset_z=0 self.staggered_pin_minlength = 0 # y-offset of back-pins in staggered mode self.staggered_pad = [] # pad size in staggered mode self.addpinstext=True self.rm_list = [] self.more_packnames = [] # additional package names, e.g. "I2PAK" for TO-262 self.webpage=""; if (name == "TO-218"): self.webpage="https://www.vishay.com/docs/95214/fto218.pdf" self.plastic = [14.94, 12.19, 4.8] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 12.19+7.79, 1.27] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 5.475 # pin distance self.pad = [2.5, 3.5] # width/height of pads self.drill = 1.5 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, 16.2] # position of mounting hole from bottom-left self.mounting_hole_diameter = 4.23 # diameter of mounting hole in package self.mounting_hole_drill = 4.04 # diameter of mounting hole drill self.pin_minlength = 2.35 # min. elongation of pins before 90° bend self.pinw = [1.15, 0.4]; # width,height of pins self.tags = ["SOT-93"] # description/keywords #self.more_packnames.append("SOT-93") self.pin_offset_z = 3.17 if largepads: self.pad = [3.5, 4.5] self.largepads = True elif (name == "TO-3P"): self.webpage="https://toshiba.semicon-storage.com/ap-en/design-support/package/detail.TO-3P(N).html" self.plastic = [15.5, 19.3, 4.5] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 20, 1.5] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 5.45 # pin distance self.pad = [2.5, 4.5] # width/height of pads self.drill = 1.5 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 3.5] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.2 # diameter of mounting hole in package self.mounting_hole_drill = 3.4 # diameter of mounting hole drill self.pin_minlength = 3.0 # min. elongation of pins before 90° bend self.pinw = [1.0, 0.6]; # width,height of pins self.tags = [] self.metal_angled=[1.15,2] self.plastic_angled = [2.19, 3.5] self.tags = [""] # description/keywords self.pin_offset_z = 3.0 self.addpinstext=True if largepads: self.pad = [3.5, 5.5] self.largepads = True elif (name == "TO-3PB"): self.webpage="http://www.onsemi.com/pub/Collateral/340AC.PDF" self.plastic = [15.6, 18.5, 4.8] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 20, 2] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 5.45 # pin distance self.pad = [2.5, 4.5] # width/height of pads self.drill = 1.5 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 3.5] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.2 # diameter of mounting hole in package self.mounting_hole_drill = 3.4 # diameter of mounting hole drill self.pin_minlength = 1.6 # min. elongation of pins before 90° bend self.pinw = [1.0, 0.6]; # width,height of pins self.tags = [] self.metal_angled=[1.3,2.3] self.plastic_angled = [2.7, 4.7] self.tags = [""] # description/keywords self.pin_offset_z = 1.7 self.addpinstext=True if largepads: self.pad = [3.5, 5.5] self.largepads = True elif (name == "TO-264"): self.webpage="https://www.fairchildsemi.com/package-drawings/TO/TO264A03.pdf" if (pins==5): self.webpage="https://www.onsemi.com/pub/Collateral/NJL3281D-D.PDF" self.plastic = [20, 26, 5] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 0, 2] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 5.45 # pin distance self.pad = [2.5, 4.5] # width/height of pads self.drill = 1.5 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 6] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.3 # diameter of mounting hole in package self.mounting_hole_drill = 3.3 # diameter of mounting hole drill self.pin_minlength = 5.08 # min. elongation of pins before 90° bend self.pinw = [1, 0.6]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = self.plastic[2] - (2.8 + 0.3) if largepads: self.pad = [3.5, 5.5] self.largepads = True elif (name == "TO-247"): self.webpage="https://toshiba.semicon-storage.com/us/product/mosfet/to-247-4l.html" if (pins==5): self.webpage="http://ww1.microchip.com/downloads/en/DeviceDoc/20005685A.pdf" self.plastic = [15.9, 20.95, 5.03] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [0, 0, 0] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 5.45 # pin distance self.pad = [2.5, 4.5] # width/height of pads self.drill = 1.5 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 6.17] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.61 # diameter of mounting hole in package self.mounting_hole_drill = 3.6 # diameter of mounting hole drill self.pin_minlength = 5.08 # min. elongation of pins before 90° bend self.pinw = [1.2, 0.6]; # width,height of pins self.tags = [] if (pins==4): self.rm_list = [5.08,2.54,2.54] self.pin_offset_z = self.plastic[2] - (2.4 + 0.3) if largepads: self.pad = [3.5, 5.5] self.largepads = True elif (name == "TO-220"): if pins==3: self.webpage="https://www.vishay.com/docs/66542/to-220-1.pdf" if (pins==2): self.webpage="https://www.centralsemi.com/PDFS/CASE/TO-220-2PD.PDF" #if (pins==4): # self.webpage="https://www.centralsemi.com/PDFS/CASE/TO-220-2PD.PDF" if (pins==5): self.webpage="http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-to-220/to-220_5_05-08-1421.pdf?domain=www.linear.com, https://www.diodes.com/assets/Package-Files/TO220-5.pdf" if staggered_type==0: self.webpage="http://www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/ltc-legacy-to-220/to-220_5_05-08-1421_straight_lead.pdf" self.plastic = [10, 9.25, 4.4] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 15.65, 1.27] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 2.54 # pin distance self.pad = [2,2] # width/height of pads self.drill = 1.1 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.metal[1] - 2.8] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.7 # diameter of mounting hole in package self.mounting_hole_drill = 3.5 # diameter of mounting hole drill self.pin_minlength = 3.81 # min. elongation of pins before 90° bend self.pinw = [0.75, 0.5]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = 3.15 self.staggered_rm = [3.7,3.8]# y-distance between pins self.staggered_pin_offset_z = 4.5 # z-offset of back-pins in staggered mode self.staggered_pin_minlength = 2.05 # y-offset of back-pins in staggered mode self.staggered_pad = [1.8, 1.8] # width/height of pads if pins == 5: self.tags.append("Pentawatt") self.tags.append("Multiwatt-5") #self.more_packnames.append("Pentawatt") #self.more_packnames.append("Multiwatt-5") self.staggered_pin_minlength = 2.05+1.28 # y-offset of back-pins in staggered mode self.rm = 1.7 self.pad = [1.3, 1.8] if pins == 9: self.pinw = [0.5, 0.38]; self.drill = 0.7 self.pad = [1.3, 1.3] self.staggered_pad = [1.5, 1.5] # width/height of pads if pins >5: self.tags.append("Multiwatt-{0}".format(pins)) #self.more_packnames.append("Multiwatt-{0}".format(pins)) if pins>9: if pins==11: self.webpage="http://www.st.com/resource/en/datasheet/tda7391lv.pdf" if pins==15: self.webpage="http://www.st.com/resource/en/datasheet/l298.pdf" self.plastic = [20.2, 10.7, 5] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 17.5,1.6] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.metal_angled = [2.25,2.25] self.pins = 15 # number of pins self.rm = 1.3 # pin distance self.pad = [1.8, 1.8] # width/height of pads self.drill = 1 # diameter of pad drills self.name = name+"-{0}".format(pins) # name of package self.addpinstext=False self.mounting_hole_pos = [self.plastic[0] / 2, 17.5-2.8] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.7 # diameter of mounting hole in package self.mounting_hole_drill = 3.5 # diameter of mounting hole drill self.pin_minlength = 3.81 # min. elongation of pins before 90° bend self.pinw = [0.7, 0.5]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = 4.55 self.staggered_rm = [5.08,2.54] # y-distance between pins self.staggered_pin_offset_z = 4.5 # z-offset of back-pins in staggered mode self.staggered_pin_minlength= 3.3 # y-offset of back-pins in staggered mode self.staggered_pad = [1.8, 1.8] # width/height of pads if largepads: if largepads: self.tags.append("large pads") self.pad = [2, 3.5] self.largepads = True elif (name == "TO-220F"): if pins==2: self.webpage="http://www.onsemi.com/pub/Collateral/FFPF10F150S-D.pdf" if pins==3: self.webpage="http://www.st.com/resource/en/datasheet/stp20nm60.pdf" if pins==4: self.webpage="https://www.njr.com/semicon/PDF/package/TO-220F-4_E.pdf" self.plastic = [10.26, 15.87-6.68, 4.7] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 15.87, 2.52] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 2.54 # pin distance self.pad = [2, 2] # width/height of pads self.drill = 1.2 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.metal[1] - 3.3] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.7 # diameter of mounting hole in package self.mounting_hole_drill = 3.5 # diameter of mounting hole drill self.pin_minlength = 3.23 # min. elongation of pins before 90° bend self.pinw = [0.6, 0.7]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = 2.76+0.575/2 self.staggered_rm = [3.7,3.8]# y-distance between pins self.staggered_pin_offset_z = 4.5 # z-offset of back-pins in staggered mode self.staggered_pin_minlength = 2.05 # y-offset of back-pins in staggered mode self.staggered_pad = [1.8, 1.8] # width/height of pads if pins == 5: self.tags.append("PentawattF-") self.tags.append("MultiwattF-5") #self.more_packnames.append("Pentawatt") #self.more_packnames.append("Multiwatt-5") self.staggered_pin_minlength = 2.05+1.28 # y-offset of back-pins in staggered mode self.rm = 1.7 self.pad = [1.3, 1.8] if pins == 9: self.pinw = [0.5, 0.38]; self.drill = 0.7 self.pad = [1.3, 1.3] self.staggered_pad = [1.5, 1.5] # width/height of pads if pins >9: if pins==11: self.webpage="http://www.ti.com/lit/ds/symlink/lm3886.pdf" self.plastic = [20.02, 10.64, 4.5] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 19.58,3.3] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.metal_angled = [2.84,2.84] self.pins = pins # number of pins self.rm = 1.7 # pin distance self.pad = [1.8, 1.8] # width/height of pads self.drill = 1 # diameter of pad drills self.name = name+"-{0}".format(pins) # name of package self.addpinstext=False self.mounting_hole_pos = [self.plastic[0] / 2, 17.5-2.8] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.7 # diameter of mounting hole in package self.mounting_hole_drill = 3.5 # diameter of mounting hole drill self.pin_minlength = 3.81 # min. elongation of pins before 90° bend self.pinw = [0.7, 0.5]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = 4.29 self.staggered_rm = [5.08,2.54] # y-distance between pins self.staggered_pin_offset_z = 4.5 # z-offset of back-pins in staggered mode self.staggered_pin_minlength= 3.3 # y-offset of back-pins in staggered mode self.staggered_pad = [1.8, 1.8] # width/height of pads self.tags.append("MultiwattF-{0}".format(pins)) #self.more_packnames.append("Multiwatt-{0}".format(pins)) if largepads: self.tags.append("large pads") self.pad = [2, 3.5] self.largepads = True elif (name == "Multiwatt"): self.plastic = [20.2, 10.7, 5] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [self.plastic[0], 17.5,1.6] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.metal_angled = [2.25,2.25] self.pins = 15 # number of pins self.rm = 1.3 # pin distance self.pad = [1.8, 1.8] # width/height of pads self.drill = 1 # diameter of pad drills self.name = name+"-{0}".format(pins) # name of package self.addpinstext=False self.mounting_hole_pos = [self.plastic[0] / 2, 17.5-2.8] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.7 # diameter of mounting hole in package self.mounting_hole_drill = 3.5 # diameter of mounting hole drill self.pin_minlength = 3.81 # min. elongation of pins before 90° bend self.pinw = [0.7, 0.5]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = 4.55 self.staggered_rm = [5.08,2.54] # y-distance between pins self.staggered_pin_offset_z = 4.5 # z-offset of back-pins in staggered mode self.staggered_pin_minlength= 3.3 # y-offset of back-pins in staggered mode self.staggered_pad = [1.8, 1.8] # width/height of pads if pins == 5: self.tags.append("Pentawatt") self.more_packnames.append("Pentawatt") if pins != 5: self.tags.append("Multiwatt-{0}".format(pins)) if largepads: self.tags.append("large pads") self.pad = [2, 3.5] self.largepads = True elif (name == "TO-126"): self.webpage="https://www.diodes.com/assets/Package-Files/TO126.pdf" self.plastic = [8, 11, 3.25] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [0, 0, 0] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 2.54 # pin distance self.pad = [1.8, 1.8] # width/height of pads self.drill = 1 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 3.9] # position of mounting hole from bottom-left self.mounting_hole_diameter = 3.2 # diameter of mounting hole in package self.mounting_hole_drill = 3.2 # diameter of mounting hole drill self.pin_minlength = 4 # min. elongation of pins before 90° bend self.pinw = [0.75, 0.5]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = 2 if largepads: self.tags.append("large pads") self.pad = [2.0, 2.3] self.largepads = True elif (name == "TO-251"): self.webpage="https://www.diodes.com/assets/Package-Files/TO251.pdf" self.plastic = [6.58, 6.1, 2.3] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [5.34, 7, 0.5] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 2.29 # pin distance self.pad = [1.8, 1.8] # width/height of pads self.drill = 1.1 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 3.9] # position of mounting hole from bottom-left self.mounting_hole_diameter = 0 # diameter of mounting hole in package self.mounting_hole_drill = 0 # diameter of mounting hole drill self.pin_minlength = 2.5 # min. elongation of pins before 90° bend self.pinw = [0.75, 0.5]; # width,height of pins self.tags = ["IPAK"] # description/keywords #self.more_packnames.append("IPAK") self.pin_offset_z = 1.27 self.additional_pin_pad_size = [5.7, 6.2] # Größe des Zusatz-SMD-Pads self.metal_offset_x = (self.plastic[0] - self.metal[0]) / 2 # offset of metal from left if largepads: self.tags.append("large pads") self.pad = [1.8, 1.8] self.additional_pin_pad_size = [6.3, 6.5] # Größe des Zusatz-SMD-Pads self.largepads = True self.additional_pin_pad = [self.plastic[0] / 2, self.metal[1] - self.additional_pin_pad_size[ 1] / 3] # Position des Zusatz-SMD-Pads elif (name == "SIPAK"): self.plastic = [6.6, 6.4, 2.3] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [5.33, 7.12, 0.4] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 2.286 # pin distance self.pad = [1.8, 1.8] # width/height of pads self.drill = 1.1 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 3.9] # position of mounting hole from bottom-left self.mounting_hole_diameter = 0 # diameter of mounting hole in package self.mounting_hole_drill = 0 # diameter of mounting hole drill self.pin_minlength = 1.02 # min. elongation of pins before 90° bend self.pinw = [0.9, 0.5]; # width,height of pins self.tags = [] # description/keywords self.pin_offset_z = 1.17+0.25 self.addpinstext=False self.additional_pin_pad_size = [5.5, 6.2] # Größe des Zusatz-SMD-Pads self.metal_offset_x = (self.plastic[0] - self.metal[0]) / 2 # offset of metal from left if largepads: self.tags.append("large pads") self.pad = [1.8, 1.8] self.additional_pin_pad_size = [6.3, 6.5] # Größe des Zusatz-SMD-Pads self.largepads = True self.additional_pin_pad = [self.plastic[0] / 2, self.metal[1] - self.additional_pin_pad_size[ 1] / 3] # Position des Zusatz-SMD-Pads elif (name == "TO-262"): self.webpage="http://www.onsemi.com/pub/Collateral/EN8586-D.PDF" if pins==5: self.webpage="http://pdf.datasheetcatalog.com/datasheet/irf/iris4011.pdf" self.plastic = [10, 9.2, 4.5] # width,heigth,depth of plastic package, starting at bottom-left self.metal = [10, 10.4, 1.3] # width,heigth,thickness of metal plate, starting at metal_offset from bottom-left self.pins = 3 # number of pins self.rm = 2.54 # pin distance self.pad = [2, 2] # width/height of pads self.drill = 1.1 # diameter of pad drills self.name = name # name of package self.mounting_hole_pos = [self.plastic[0] / 2, self.plastic[1] - 3.9] # position of mounting hole from bottom-left self.mounting_hole_diameter = 0 # diameter of mounting hole in package self.mounting_hole_drill = 0 # diameter of mounting hole drill self.pin_minlength = 3.25 # min. elongation of pins before 90° bend self.pinw = [0.8, 0.5]; # width,height of pins self.tags = ["IIPAK", "I2PAK"] # description/keywords #self.more_packnames.append("I2PAK") self.pin_offset_z = 2.65 self.additional_pin_pad_size = [10, 8] # Größe des Zusatz-SMD-Pads self.metal_offset_x = (self.plastic[0] - self.metal[0]) / 2 # offset of metal from left if largepads: self.tags.append("large pads") self.pad = [1.8, 1.8] self.additional_pin_pad_size = [6.3, 6.5] # Größe des Zusatz-SMD-Pads self.largepads = True self.additional_pin_pad = [self.plastic[0] / 2, self.metal[1] - self.additional_pin_pad_size[ 1] / 3] # Position des Zusatz-SMD-Pads else: print("DID NOT FIND '", name,"'") self.__init__() if rm > 0: self.rm = rm if self.addpinstext: self.name = "{0}-{1}".format(self.name, pins) if pins != 3: self.pins = pins if rm <= 0: self.rm = 2 * self.rm / (pins - 1) else: self.rm = rm; self.pin_offset_x = (self.plastic[0] - (self.pins - 1) * self.rm) / 2 if len(self.rm_list)>0: pl=0 for rm in self.rm_list: pl=pl+rm self.pin_offset_x = (self.plastic[0] - pl) / 2 self.pad[0] = min(self.pad[0], 0.75 * self.rm) if self.largepads: self.tags.append("large pads") if self.staggered_type==1: self.tags.append("staggered type-1") self.fpnametags=["StaggeredType1"]+self.fpnametags if self.staggered_type==2: self.tags.append("staggered type-2") self.fpnametags=["StaggeredType2"] + self.fpnametags if pitchy>0: self.staggered_rm = [pitchy,pitchy] # y-distance between pins if ypinoffset!=0: self.pin_offset_z = ypinoffset crt_offset = 0.25 slk_offset = 0.12 slk_dist = 0.15 lw_fab = 0.1 lw_crt = 0.05 lw_slk = 0.12 txt_offset = 1 ================================================ FILE: scripts/Packages/TO_SOT_THT/tools.py ================================================ #!/usr/bin/env python import sys import os import math import time # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..","..")) # load kicad_mod path from KicadModTree import * # NOQA # round for grid g def roundG(x, g): if (x>0): return math.ceil(x/g)*g else: return math.floor(x/g)*g # round for courtyard grid def roundCrt(x): return roundG(x, 0.01) # float-variant of range() def frange(x, y, jump): while x < y: yield x x += jump # inclusice float-variant of range() def frangei(x, y, jump): while x <= y: yield x x += jump # returns a list with a single rectangle around x,y with width and height w and h def addKeepoutRect(x, y, w, h): return [[x - w / 2, x + w / 2, y - h / 2, y + h / 2]] # returns a series of rectangle that lie around the circular pad around (x,y) with radius w=h # if w!=h, addKeepoutRect() is called def addKeepoutRound(x,y, w,h): if w!=h: return addKeepoutRect(x,y,w,h) else: res=[] Nrects=4 r=max(h,w)/2 yysum=0 for ya in frange(0,r,r/Nrects): a=math.fabs(math.asin(ya/r)/math.pi*180) yy=math.fabs(r*math.sin(a/180.0*math.pi)) xx=math.fabs(r*math.cos(a/180.0*math.pi)) if (xx>0): res.append([x - xx-0.015, x + xx+0.015, y-yy-r/Nrects-0.015, y-yy+.015]) res.append([x - xx-0.015, x + xx+0.015, y+yy-0.015, y+yy+r/Nrects+0.015]) yysum=yysum+yy return res def applyKeepouts(lines_in, y, xi, yi, keepouts): #print(" applyKeepouts(\n lines_in=", lines_in, " \n y=", y, " \n xi=", xi, " yi=", yi, " \n keepouts=", keepouts, ")") lines=lines_in changes = True while (changes): changes = False for ko in keepouts: ko = [min(ko[0], ko[1]), max(ko[0], ko[1]), min(ko[2], ko[3]), max(ko[2], ko[3])] if (ko[yi+0] <= y) and (y <= ko[yi+1]): #print(" INY: koy=", [ko[yi + 0], ko[yi + 1]], " y=", y, "): kox=", [ko[xi + 0], ko[xi + 1]]) for li in reversed(range(0, len(lines))): l = lines[li] if (l[0] >= ko[xi+0]) and (l[0] <= ko[xi+1]) and (l[1] >= ko[xi+0]) and (l[1] <= ko[xi+1]): # Line completely inside -> remove lines.pop(li) #print(" H1: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, ")") changes = True elif (l[0] >= ko[xi+0]) and (l[0] <= ko[xi+1]) and (l[1] > ko[xi+1]): # Line starts inside, but ends outside -> remove and add shortened lines.pop(li) lines.append([ko[xi+1], l[1]]) #print(" H2: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ", [ko[xi+1], l[1]]) changes = True elif (l[0] < ko[xi+0]) and (l[1] <= ko[xi+1]) and (l[1] >= ko[xi+0]): # Line starts outside, but ends inside -> remove and add shortened lines.pop(li) lines.append([l[0], ko[xi+0]]) #print(" H3: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ", [l[0], ko[xi+0]]) changes = True elif (l[0] < ko[xi+0]) and (l[1] > ko[xi+1]): # Line starts outside, and ends outside -> remove and add 2 shortened lines.pop(li) lines.append([l[0], ko[xi+0]]) lines.append([ko[xi+1], l[1]]) #print(" H4: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ", [l[0], ko[xi+0]], [ko[xi+1], l[1]]) changes = True #else: #print(" USE: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ") if changes: break return lines #split a vertical line so it does not interfere with keepout areas defined as [[x0,x1,y0,y1], ...] def addHLineWithKeepout(kicad_mod, x0, x1, y,layer, width, keepouts=[], roun=0.001): #print("addHLineWithKeepout",y) linesout = applyKeepouts([[min(x0,x1), max(x0,x1)]], y, 0,2,keepouts) for l in linesout: kicad_mod.append(Line(start=[roundG(l[0], roun), roundG(y, roun)], end=[roundG(l[1], roun), roundG(y, roun)], layer=layer, width=width)) # split a vertical line into dashes, so it does not interfere with keepout areas defined as [[x0,x1,y0,y1], ...] def addHDLineWithKeepout(kicad_mod, x0, dx, x1, y, layer, width, keepouts=[], roun=0.001): #print("addHDLineWithKeepout",y) x=min(x0,x1) lines=[] on=True while (x+dx)<=max(x0,x1): if (on): lines.append([x,x+dx]) x=x+dx on=not on if (x 0.625 # | Minimum | Median | Maximum | # | (Least) | (Nominal) | (Most) | # | Density | Density | Density | round # Lead Part | Level C | Level B | Level A | to # ----------+---------+-----------+---------+- # Toe | 0.15 | 0.35 | 0.55 | 0.2 # Heel | 0.25 | 0.35 | 0.45 | 0.2 # Side | 0.01 | 0.03 | 0.05 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 | ipc_spec_gw_large_pitch: least: toe: 0.15 heel: 0.25 side: 0.01 courtyard: 0.1 nominal: toe: 0.35 heel: 0.35 side: 0.03 courtyard: 0.25 most: toe: 0.55 heel: 0.45 side: 0.05 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 # Gull-Wing (L-Lead) pitch <= 0.625 # | Minimum | Median | Maximum | # | (Least) | (Nominal) | (Most) | # | Density | Density | Density | round # Lead Part | Level C | Level B | Level A | to # ----------+---------+-----------+---------+- # Toe | 0.15 | 0.35 | 0.55 | 0.05 # Heel | 0.25 | 0.35 | 0.45 | 0.05 # Side | -0.04 | -0.02 | 0.01 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 | ipc_spec_gw_small_pitch: least: toe: 0.15 heel: 0.25 side: -0.04 courtyard: 0.1 nominal: toe: 0.35 heel: 0.35 side: -0.02 courtyard: 0.25 most: toe: 0.55 heel: 0.45 side: 0.01 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 # J Lead # | Minimum | Median | Maximum | # | (Least) | (Nominal) | (Most) | # | Density | Density | Density | round # Lead Part | Level C | Level B | Level A | to # ----------+---------+-----------+---------+- # Toe | -0.1 | 0.0 | 0.1 | 0.05 # Heel | 0.15 | 0.35 | 0.55 | 0.05 # Side | 0.01 | 0.03 | 0.05 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 | ipc_spec_j_lead: least: toe: -0.1 heel: 0.15 side: 0.01 courtyard: 0.1 nominal: toe: 0.0 heel: 0.35 side: 0.03 courtyard: 0.25 most: toe: 0.1 heel: 0.25 side: 0.05 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 # Flat No Lead (DFN/QFN) with toe fillet # | Minimum | Median | Maximum | # | (Least) | (Nominal) | (Most) | # | Density | Density | Density | round # Lead Part | Level C | Level B | Level A | to # ----------+---------+-----------+---------+- # Toe | 0.2 | 0.3 | 0.4 | 0.05 # Heel | 0.0 | 0.0 | 0.0 | 0.05 # Side | -0.04 | -0.04 | -0.04 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 | ipc_spec_flat_no_lead: least: toe: 0.2 heel: 0.0 side: -0.04 courtyard: 0.1 nominal: toe: 0.3 heel: 0.0 side: -0.04 courtyard: 0.25 most: toe: 0.4 heel: 0.0 side: -0.04 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 # Flat No Lead pull back # # | Minimum | Median | Maximum | # | (Least) | (Nominal) | (Most) | # | Density | Density | Density | round # Lead Part | Level C | Level B | Level A | to # ----------+---------+-----------+---------+- # Toe | -0.05 | 0.0 | 0.05 | 0.05 # Heel | -0.05 | 0.0 | 0.05 | 0.05 # Side | -0.05 | -0.0 | 0.05 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 | ipc_spec_flat_no_lead_pull_back: least: toe: -0.05 heel: -0.05 side: -0.05 courtyard: 0.1 nominal: toe: 0.0 heel: 0.0 side: 0.0 courtyard: 0.25 most: toe: 0.05 heel: 0.05 side: 0.05 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 ================================================ FILE: scripts/Packages/package_config_KLCv3.yaml ================================================ fp_name_format_string: '{man:s}_{mpn:s}_{pkg:s}-{pincount:d}_{size_x:.1f}x{size_y:.1f}mm_P{pitch:.2f}mm{suffix:s}' fp_name_format_string_pincount_text: '{man:s}_{mpn:s}_{pkg:s}-{pincount:s}_{size_x:.1f}x{size_y:.1f}mm_P{pitch:.2f}mm{suffix:s}' keyword_fp_string: '{man:s} {package:s} {category:s}' lib_name_format_string: 'Package_{category:s}' fp_name_format_string_no_trailing_zero: '{man:s}_{mpn:s}_{pkg:s}-{pincount:d}_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}{suffix2:s}' fp_name_format_string_no_trailing_zero_pincount_text: '{man:s}_{mpn:s}_{pkg:s}-{pincount:s}_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}{suffix2:s}' fp_name_lga_format_string_no_trailing_zero: '{man:s}_{mpn:s}_{pkg:s}-{pincount:d}_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{layout:s}{suffix:s}{suffix2:s}' lga_layout_grid: '_LayoutGrid{nx:d}x{ny:d}' lga_layout_border: '_LayoutBorder{nx:d}x{ny:d}y' fp_name_EP_format_string_no_trailing_zero: '{man:s}_{mpn:s}_{pkg:s}-{pincount:d}-1EP_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}_EP{ep_size_x:g}x{ep_size_y:g}mm{suffix2:s}{vias:s}' fp_name_EP_format_string_no_trailing_zero_pincount_text: '{man:s}_{mpn:s}_{pkg:s}-{pincount:s}-1EP_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}_EP{ep_size_x:g}x{ep_size_y:g}mm{suffix2:s}{vias:s}' fp_name_EP_custom_mask_format_string_no_trailing_zero: '{man:s}_{mpn:s}_{pkg:s}-{pincount:d}-1EP_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{suffix2:s}{vias:s}' fp_name_EP_custom_mask_format_string_no_trailing_zero_pincount_text: '{man:s}_{mpn:s}_{pkg:s}-{pincount:s}-1EP_{size_x:g}x{size_y:g}mm_P{pitch:g}mm{suffix:s}_EP{ep_size_x:g}x{ep_size_y:g}mm_Mask{mask_size_x:g}x{mask_size_y:g}mm{suffix2:s}{vias:s}' thermal_via_suffix: "_ThermalVias" ================================================ FILE: scripts/Packages/utils/ep_handling_utils.py ================================================ #!/usr/bin/env python3 from KicadModTree.nodes.base.Pad import Pad def getEpRoundRadiusParams(device_params, configuration, pad_radius): pad_shape_details = {} pad_shape_details['shape'] = Pad.SHAPE_ROUNDRECT pad_shape_details['paste_radius_ratio'] = configuration['paste_radius_ratio'] pad_shape_details['paste_maximum_radius'] = configuration['paste_maximum_radius'] if 'EP_round_radius' in device_params: if type(device_params['EP_round_radius']) in [float, int]: pad_shape_details['round_radius_exact'] = device_params['EP_round_radius'] elif device_params['EP_round_radius'] == "pad": pad_shape_details['round_radius_exact'] = pad_radius else: raise TypeError( "round radius must be a number or 'pad', is {}" .format(type(device_params['EP_round_radius'])) ) elif 'EP_round_radius_ratio' in device_params: pad_shape_details['radius_ratio'] = device_params['EP_round_radius_ratio'] elif 'EP_round_radius_ratio' in configuration: pad_shape_details['radius_ratio'] = configuration['EP_round_radius_ratio'] else: pad_shape_details['radius_ratio'] = 0 if 'radius_ratio' in pad_shape_details and pad_shape_details['radius_ratio'] > 0: if 'EP_maximum_radius' in device_params: pad_shape_details['maximum_radius'] = device_params['EP_maximum_radius'] elif 'EP_maximum_radius' in configuration: pad_shape_details['maximum_radius'] = configuration['EP_maximum_radius'] else: pad_shape_details['maximum_radius'] = 0.25 return pad_shape_details ================================================ FILE: scripts/PadGenerator/RingPad.py ================================================ import sys import os sys.path.append(os.path.join(sys.path[0],"..","..")) import argparse from KicadModTree import * if __name__ == "__main__": parser = argparse.ArgumentParser(description='Commandline tool for generating ring pads.') parser.add_argument('-n', '--name', metavar='fp_name', type=str, help='Name of the generated footprint. default: output', default='output') parser.add_argument('--at', type=float, nargs=2, help='position of the pad, default: at origin', default=[0,0], metavar=('x', 'y')) parser.add_argument('-v', '--verbose', action='count', help='set debug level') parser.add_argument('-i', '--inner_diameter', type=float, help='inside diameter', required=True) parser.add_argument('-o', '--outer_diameter', type=float, help='outside diameter', required=True) parser.add_argument('-p', '--number', type=str, help='the pin number, default: 1', default='1') parser.add_argument('--anchor_count', type=int, help='number of anchor (trace connection points), default: 4', default=4) parser.add_argument('--paste_count', type=int, help='number of paste areas, default: 4', default=4) parser.add_argument('--paste_round_radius_radio', type=float, help='round radius ratio for the paste pads', default=0.25) parser.add_argument('--paste_clearance', type=float, help='clearance between paste areas', nargs='?') parser.add_argument('--mask_margin', type=float, help='soldermask margin, default:0', default=0) parser.add_argument('--paste_margin', type=float, help='solderpaste margin, default:0 (means controlled by footprint or board setup)', default=0) args = parser.parse_args() kicad_mod = Footprint(args.name) kicad_mod.append( RingPad( number=args.number, at=args.at, size=args.outer_diameter, inner_diameter=args.inner_diameter, num_anchor=args.anchor_count, num_paste_zones=args.paste_count, solder_paste_margin=args.paste_margin, solder_mask_margin=args.mask_margin, paste_round_radius_radio=args.paste_round_radius_radio, paste_to_paste_clearance=args.paste_clearance)) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(args.name + '.kicad_mod') ================================================ FILE: scripts/Potentiometers/make_Potentiometer_SMD.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_potentiometers import * if __name__ == '__main__': script3d_tsl="trimmer_screwleft.py" with open(script3d_tsl, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_tst="trimmer_screwtop.py" with open(script3d_tst, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_tsl_smd="trimmer_screwleft_smd.py" with open(script3d_tsl_smd, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_tst_smd="trimmer_screwtop_smd.py" with open(script3d_tst_smd, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_pv="pots_ver.py" with open(script3d_pv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trv="trim_round_ver.py" with open(script3d_trv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh="trim_round_hor.py" with open(script3d_trh, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh_bel="trim_round_hor_below.py" with open(script3d_trh_bel, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh_smd="trim_round_smd_hor.py" with open(script3d_trh_smd, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh_smd_bel="trim_round_smd_hor_below.py" with open(script3d_trh_smd_bel, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_ph_bel="pots_hor_below.py" with open(script3d_ph_bel, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_ph="pots_hor.py" with open(script3d_ph, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") # this footprint is not generated on-center due to design limitations of footprint_scripts_potentiometers.py class_name="Bourns PRS11S"; add_description="http://www.bourns.com/docs/Product-Datasheets/PRS11S.pdf" pins = 5; rmx=16.5; rmy=2.5; ddrill=1; wbody=13; hbody=11.7; height3d = 7.2; wscrew=4.3; dscrew=6.8 wshaft=20-wbody-wscrew; dshaft=6; pinxoffset=1.75; pinyoffset=(hbody-2*rmy)/2.0; dbody=0; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=6.5; c_offsety=hbody/2.0; mh_rmy=11.3 makePotentiometerVertical(SMD_pads=True, SMD_padsize=[4,2], mh_ddrill=1.5, mh_count=2, mh_rmx=0, mh_rmy=mh_rmy, mh_xoffset=8.25, mh_yoffset=(mh_rmy-2*rmy)/2.0, mh_nopads=True, shaft_hole=False, class_name=class_name, wbody=wbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="ACP CA6-VSMD"; add_description="http://www.acptechnologies.com/wp-content/uploads/2017/06/01-ACP-CA6.pdf" pins = 3; rmx=8.65; rmy=4.3/2.0; ddrill=0.9; wbody=6.5; hbody=6.5; dbody=0; height3d = 4.5+hbody/2.0; screwzpos = 4.5; wscrew=-wbody; dscrew=2 wshaft=0; dshaft=1.8; pinxoffset=1.075; pinyoffset=(hbody-2*rmy)/2.0; dbody=0; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=3.525; c_offsety=hbody/2.0; c_ddrill=2.5 makePotentiometerVertical(SMD_pads=True, SMD_padsize=[2.5,2], style="trimmer", shaft_hole=False, class_name=class_name, wbody=wbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=pinxoffset,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_smd,height3d=height3d) makePotentiometerVertical(SMD_pads=True, SMD_padsize=[2.5,2], style="trimmer", shaft_hole=True, class_name=class_name, wbody=wbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=pinxoffset,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_smd_bel,height3d=height3d) class_name="ACP CA9-VSMD"; add_description="http://www.acptechnologies.com/wp-content/uploads/2017/05/02-ACP-CA9-CE9.pdf" pins = 3; rmx=9.25; rmy=2.5; ddrill=1.3; hbody=9.8; wbody=10; dbody=0; screwzpos = 7; wscrew=-wbody; dscrew=3 wshaft=0; dshaft=2.1; pinxoffset=-0.375; pinyoffset=(hbody-2*rmy)/2.0; dbody=0; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=5.125; c_offsety=hbody/2.0; c_ddrill=4; height3d=5.5 makePotentiometerVertical(SMD_pads=True, SMD_padsize=[2.5,2.5], style="trimmer", shaft_hole=False, class_name=class_name, wbody=wbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=pinxoffset,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_smd,height3d=height3d) makePotentiometerVertical(SMD_pads=True, SMD_padsize=[2.5,2.5], style="trimmer", shaft_hole=True, class_name=class_name, wbody=wbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=pinxoffset,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_smd_bel,height3d=height3d) class_name="ACP CA14-VSMD"; add_description="http://www.acptechnologies.com/wp-content/uploads/2017/10/03-ACP-CA14-CE14.pdf" pins = 3; rmx=13; rmy=5; dbody=0; pinxoffset=-0.7; wbody=14; hbody=14; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=7; c_offsety=hbody/2.0; c_ddrill=7; height3d=5.8 makePotentiometerVertical(SMD_pads=True, SMD_padsize=[3,3], style="trimmer", shaft_hole=False, class_name=class_name, wbody=wbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=pinxoffset,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_smd,height3d=height3d) makePotentiometerVertical(SMD_pads=True, SMD_padsize=[3,3], style="trimmer", shaft_hole=True, class_name=class_name, wbody=wbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=pinxoffset,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_smd_bel,height3d=height3d) class_name="Bourns 3214W"; add_description = "https://www.bourns.com/docs/Product-Datasheets/3214.pdf" wbody=4.8; hbody=3.5; pinxoffset=(wbody-2.5)/2.0+2.5; pinyoffset=0.3; height3d = 5.1; rmx2=-1.25; rmy2=2.9; rmx3=-2.5; rmy3=0; ddrill=0.8; dscrew=1.5; wscrew = dscrew; screwxoffset = 1.2; screwyoffset = hbody-1.1 style = "screwtop"; SMD_pads = True; SMD_padsize = [1.3,1.6,2,1.6,1.3,1.6] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Bourns 3214X" wbody=4.8; hbody=3.5; pinxoffset=(wbody-2.5)/2.0+2.5; pinyoffset=-(5.1-3.5)/2.0; height3d = 5.3; rmx2=-1.15; rmy2=5.1; rmx3=-2.3; rmy3=0; ddrill=0.8; dscrew=1.5; wscrew = dscrew; screwxoffset = 1.2; screwyoffset = hbody-1.1 style = "screwtop"; SMD_pads = True; SMD_padsize = [1.3,1.9,2,1.9,1.3,1.9] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Bourns 3214G" wbody=4.6; hbody=4.8; pinxoffset=(wbody-5.2)/2.0+5.2; pinyoffset=(hbody-2.3)/2.0; height3d = 3.71; rmx2=-5.2; rmy2=1.15; rmx3=0; rmy3=2.3; ddrill=0.8; dscrew=1.78; wscrew = 0; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = True; SMD_padsize = [1.3,1.3,1.3,2,1.3,1.3] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3214J" wbody=4.6; hbody=4.8; pinxoffset=(wbody-4)/2.0+4; pinyoffset=(hbody-2.3)/2.0; height3d = 3.71; rmx2=-4; rmy2=1.15; rmx3=0; rmy3=2.3; ddrill=0.8; dscrew=1.78; wscrew = 0; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = True; SMD_padsize = [2,1.3,2,2,2,1.3] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3314J"; add_description = "http://www.bourns.com/docs/Product-Datasheets/3314.pdf" pins = 3; wbody=4.5; hbody=4.5; rmx2=-1.15; rmy2=4.0; rmx3=-2.3; rmy3=0; pinxoffset=(wbody+rmx3)/2.0-rmx3; pinyoffset=(hbody-rmy2)/2.0; height3d = 2.55; ddrill=0.8; dscrew=2.0; wscrew = 0; screwxoffset = wbody/2.0; screwyoffset = hbody/2.0 style = "screwtop"; SMD_pads = True; SMD_padsize = [1.3,2.0,2.0,2.0,1.3,2.0] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Bourns 3314G" pinyoffset=-1.25; rmy2 = 5.5; pinxoffset=(wbody+rmx3)/2.0-rmx3; pinyoffset=(hbody-rmy2)/2.0; SMD_padsize = [1.3,1.3,2.0,1.3,1.3,1.3] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Bourns 3314R-1" wbody=5.0; pinxoffset=(wbody+rmx3)/2.0-rmx3; screwxoffset = wbody/2.0; ddrill = 3.2 makeSpindleTrimmer(shaft_hole=True, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3314R-GM5" rmx2=-1.155; rmy2 = 6.25; rmx3=-2.31; pinxoffset=(wbody+rmx3)/2.0-rmx3; pinyoffset=(hbody-rmy2)/2.0 makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3314S" wbody = 5.01; rmx2=-1.15; rmy2 = 4.05; rmx3=-2.3; pinxoffset=(wbody+rmx3)/2.0-rmx3; pinyoffset=(hbody-rmy2)/2.0; height3d = 5.61; screwxoffset = wbody/2.0; style = "screwleft"; SMD_padsize = [1.2,1.75,1.6,1.75,1.2,1.75] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3224W"; add_description = "https://www.bourns.com/docs/Product-Datasheets/3224.pdf" wbody=4.8; hbody=3.5; pinxoffset=(wbody-2.5)/2.0+2.5; pinyoffset=0.3; height3d = 5.1; rmx2=-1.25; rmy2=2.9; rmx3=-2.5; rmy3=0; ddrill=0.8; dscrew=1.5; wscrew = dscrew; screwxoffset = 1.2; screwyoffset = hbody-1.1 style = "screwtop"; SMD_pads = True; SMD_padsize = [1.3,1.6,2,1.6,1.3,1.6] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Bourns 3224X" wbody=4.8; hbody=3.5; pinxoffset=(wbody-2.5)/2.0+2.5; pinyoffset=-(5.1-3.5)/2.0; height3d = 5.3; rmx2=-1.15; rmy2=5.1; rmx3=-2.3; rmy3=0; ddrill=0.8; dscrew=1.5; wscrew = dscrew; screwxoffset = 1.2; screwyoffset = hbody-1.1 style = "screwtop"; SMD_pads = True; SMD_padsize = [1.3,1.9,2,1.9,1.3,1.9] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Bourns 3224G" wbody=4.6; hbody=4.8; pinxoffset=(wbody-5.2)/2.0+5.2; pinyoffset=(hbody-2.3)/2.0; height3d = 3.71; rmx2=-5.2; rmy2=1.15; rmx3=0; rmy3=2.3; ddrill=0.8; dscrew=1.78; wscrew = 0; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = True; SMD_padsize = [1.3,1.3,1.3,2,1.3,1.3] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3224J" wbody=4.6; hbody=4.8; pinxoffset=(wbody-4)/2.0+4; pinyoffset=(hbody-2.3)/2.0; height3d = 3.71; rmx2=-4; rmy2=1.15; rmx3=0; rmy3=2.3; ddrill=0.8; dscrew=1.78; wscrew = 0; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = True; SMD_padsize = [2,1.3,2,2,2,1.3] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3269W"; add_description = "https://www.bourns.com/docs/Product-Datasheets/3269.pdf" wbody=6.35; hbody=4.32; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=-0.25; height3d = 7.44; rmx2=-2.54; rmy2=4.83; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=1.78; wscrew = dscrew; screwxoffset = wbody-1.002; screwyoffset = hbody-1.52 style = "screwtop"; SMD_pads = True; SMD_padsize = [1.19,2.79] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Bourns 3269X" wbody=6.35; hbody=4.32; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=-0.25; height3d = 7.44; rmx2=-2.54; rmy2=4.83; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=1.78; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody-1.52 style = "screwleft"; SMD_pads = True; SMD_padsize = [1.19,2.79] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Bourns 3269P" wbody=6.35; hbody=6.35; pinxoffset=-(wbody-6.4)/2.0+6.4; pinyoffset=(hbody-5.08)/2.0; height3d = 5.21; rmx2=-6.4; rmy2=2.54; rmx3=0; rmy3=5.08; ddrill=0.8; dscrew=1.78; wscrew = 1.52; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = True; SMD_padsize = [3.3,1.19] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl_smd, height3d=height3d) class_name="Vishay TS53YJ"; add_description = "https://www.vishay.com/docs/51008/ts53.pdf" wbody=5; hbody=5; pinxoffset=0.5+4; pinyoffset=(5-2.3)/2.0; height3d = 2.7; rmx2=-4; rmy2=1.15; rmx3=0; rmy3=2.3; ddrill=0.8; dscrew=2.3; wscrew = dscrew; screwxoffset = wbody/2.0; screwyoffset = hbody/2.0 SMD_pads = True; SMD_padsize = [2,1.3,2,2,2,1.3] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, screwstyle="cross", ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style="screwtop", SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) class_name="Vishay TS53YL" wbody=5; hbody=5; pinxoffset=-0.25+5.5; pinyoffset=(5-2.3)/2.0; height3d = 2.7; rmx2=-5.5; rmy2=1.15; rmx3=0; rmy3=2.3; ddrill=0.8; dscrew=2.3; wscrew = dscrew; screwxoffset = wbody/2.0; screwyoffset = hbody/2.0 SMD_pads = True; SMD_padsize = [1.3,1.3,2,1.3,1.3,1.3] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, screwstyle="cross", ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style="screwtop", SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst_smd, height3d=height3d) ================================================ FILE: scripts/Potentiometers/make_Potentiometer_THT.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_potentiometers import * if __name__ == '__main__': script3d_tsl="trimmer_screwleft.py" with open(script3d_tsl, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_tst="trimmer_screwtop.py" with open(script3d_tst, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_tsl_smd="trimmer_screwleft_smd.py" with open(script3d_tsl_smd, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_tst_smd="trimmer_screwtop_smd.py" with open(script3d_tst_smd, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_pv="pots_ver.py" with open(script3d_pv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trv="trim_round_ver.py" with open(script3d_trv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh="trim_round_hor.py" with open(script3d_trh, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh_bel="trim_round_hor_below.py" with open(script3d_trh_bel, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh_smd="trim_round_smd_hor.py" with open(script3d_trh_smd, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_trh_smd_bel="trim_round_smd_hor_below.py" with open(script3d_trh_smd_bel, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_ph_bel="pots_hor_below.py" with open(script3d_ph_bel, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3d_ph="pots_hor.py" with open(script3d_ph, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") R_POW = 0 class_name="Omeg PC16BU"; add_description="http://www.omeg.co.uk/pc6bubrc.htm" pins = 3; rmx=5.0; rmy=5.; ddrill=1.3; wbody=9.3; hbody=16.9; height3d = 21; screwzpos = 12.5; wscrew=6; dscrew=7 wshaft=50-wscrew; dshaft=4; pinxoffset=6.3; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) voffsetx=1.75; dbody=16.9; vwbody=5; vpinyoffset=(hbody-2*rmy)/2.0; c_offsety=dbody/2.0; c_offsetx=10.8 #makePotentiometerVertical(shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) makePotentiometerVertical(shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph,height3d=height3d) class_name="Vishay 248GJ-249GJ Single"; add_description="http://www.vishay.com/docs/57054/248249.pdf" pins = 3; rmx=7.62; rmy=2.54; ddrill=1; wbody=7.6; hbody=12.5; height3d = 13.1; screwzpos = 12.7/2.0+0.6; wscrew=9.5; dscrew=(3/8.0)*25.4 wshaft=22.22-wscrew; dshaft=(1/4.0)*25.4; pinxoffset=5.08; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) voffsetx=0.75; dbody=0; vwbody=12.7; vpinyoffset=(hbody-2*rmy)/2.0; c_offsety=hbody/2.0; c_offsetx=vwbody/2.0 #makePotentiometerVertical(shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) makePotentiometerVertical(shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph,height3d=height3d) class_name="Vishay 248BH-249BH Single"; add_description="http://www.vishay.com/docs/57054/248249.pdf" wscrew=9.5; dscrew=0.25*25.4; wshaft=19.05-wscrew; dshaft=3.18; pinxoffset=5.08; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Vishay 148-149 Single"; add_description="http://www.vishay.com/docs/57040/148149.pdf" pins = 3; rmx=7.62; rmy=2.54; ddrill=1; wbody=8.83; hbody=12.5; height3d = 13.1; screwzpos = 12.5/2.0+0.6; wscrew=6.35; dscrew=0.25*25.4 wshaft=12.8-wscrew; dshaft=3.17; pinxoffset=5.08; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) voffsetx=0.75; dbody=0; vwbody=12.5; vpinyoffset=(hbody-2*rmy)/2.0; c_offsety=hbody/2.0; c_offsetx=vwbody/2.0 #makePotentiometerVertical(shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) makePotentiometerVertical(shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph,height3d=height3d) class_name="Vishay 148E-149E Single" wbody = 6.35 + 3.85 + 1.52 + 0.5 makePotentiometerHorizontal(mh_ddrill=1.3, mh_count=4, mh_rmx=3.85+6.35, mh_rmy=10.16, mh_xoffset=3.85, mh_yoffset=(10.16-2*rmy)/2.0, class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Vishay 148-149 Dual" pins = 6; wbody=16.45; wscrew=7 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Vishay 148E-149E Dual" wbody = 6.35+7.62+3.85+1.52+0.5 makePotentiometerHorizontal(mh_ddrill=1.3, mh_count=4, mh_rmx=3.85+7.62+6.35, mh_rmy=10.16, mh_xoffset=3.85, mh_yoffset=(10.16-2*rmy)/2.0, class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PC-16 Single"; add_description="http://www.piher-nacesa.com/pdf/20-PC16v03.pdf" pins = 3; rmx=7.5; rmy=5.0; ddrill=1.3; wbody=8; hbody=16; height3d = 20.5; screwzpos = 12.5; wscrew=9; dscrew=10 wshaft=25-wscrew; dshaft=6; pinxoffset=6.5; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) voffsetx = 0.5; dbody = 0; vwbody = 18; vpinyoffset = (hbody-2*rmy)/2.0; c_offsetx = 10; c_offsety = hbody/2.0 #makePotentiometerVertical(shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) makePotentiometerVertical(shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph,height3d=height3d) #class_name="Piher PC-16SV Single" #voffsetx=0.5; dbody=0; vwbody=18; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=10; c_offsety=hbody/2.0 #makePotentiometerVertical(mh_ddrill=1.3, mh_count=2, mh_rmx=0, mh_rmy=10.0, mh_xoffset=15, mh_yoffset=(10-2*rmy)/2.0, shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Piher PC-16 Dual" pins = 6; wbody=16 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PC-16 Triple" pins = 9; wbody=24 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Piher T-16H Single"; add_description="http://www.piher-nacesa.com/pdf/22-T16v03.pdf" pins = 3; rmx=7.5; rmy=5.0; ddrill=1.3; wbody=7.5; hbody=16; height3d = 21; screwzpos = 12.5; wscrew=5; dscrew=7 wshaft=15-wscrew; dshaft=4; pinxoffset=1.5; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Piher T-16L Single" voffsetx=-0.5; dbody=16; vwbody=3; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=10.5; c_offsety=hbody/2.0 makePotentiometerVertical(shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Piher T-16H Double" pins = 6; wbody=15 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Alps RK163 Single"; add_description="http://www.alps.com/prod/info/E/HTML/Potentiometer/RotaryPotentiometers/RK16/RK16_list.html" pins = 3; rmx=5.0; rmy=5.0; ddrill=1.3; wbody=10.5; hbody=17.9; height3d = 21; screwzpos = 12.5; wscrew=5; dscrew=7 wshaft=15-wscrew; dshaft=6; pinxoffset=3.8; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Alps RK163 Dual" pins = 6; wbody=12.1; wscrew=7 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Alps RK097 Single"; add_description="http://www.alps.com/prod/info/E/HTML/Potentiometer/RotaryPotentiometers/RK097/RK097_list.html" pins = 3; rmx=2.5; rmy=2.5; ddrill=1; wbody=7.05; hbody=9.5; height3d = 6.5+0.25+4.85; screwzpos = 6.5+0.25; wscrew=5; dscrew=7 wshaft=15-wscrew; dshaft=6; pinxoffset=5; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Alps RK097 Dual" pins = 6; wbody=9.55 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Bourns PTV09A-2 Single"; add_description="http://www.bourns.com/docs/Product-Datasheets/ptv09.pdf" pins = 3; rmx=2.5; rmy=2.5; ddrill=1; wbody=5; hbody=9.7; height3d = 10+5.5; screwzpos = 10; wscrew=0.8; dscrew=6.8 wshaft=15-wbody-wscrew; dshaft=6; pinxoffset=3.5; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(mh_ddrill=2.3, mh_count=2, mh_rmx=0, mh_rmy=10, mh_xoffset=-3.3, mh_yoffset=(10-2*rmy)/2.0, class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Bourns PTV09A-1 Single" voffsetx=1; dbody=0; vwbody=12; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=6.5; c_offsety=hbody/2.0 makePotentiometerVertical(mh_ddrill=2, mh_count=2, mh_rmx=0, mh_rmy=8.8, mh_xoffset=7, mh_yoffset=(8.8-2*rmy)/2.0, shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Alps RK09K Single"; add_description="http://www.alps.com/prod/info/E/HTML/Potentiometer/RotaryPotentiometers/RK09K/RK09K_list.html" pins = 3; rmx=2.5; rmy=2.5; ddrill=1; wbody=6.8; hbody=9.8; height3d = 6.5+5.5; screwzpos = 6.5; wscrew=0.8; dscrew=6.5 wshaft=15-6.8-wscrew; dshaft=6; pinxoffset=3.4; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(mh_ddrill=2.3, mh_count=2, mh_rmx=0, mh_rmy=10, mh_xoffset=-3.3, mh_yoffset=(10-2*rmy)/2.0, class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Alps RK09K Single" voffsetx=1; dbody=0; vwbody=12; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=6.5; c_offsety=hbody/2.0 makePotentiometerVertical(mh_ddrill=2, mh_count=2, mh_rmx=0, mh_rmy=8.8, mh_xoffset=7, mh_yoffset=(8.8-2*rmy)/2.0, shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Alps RK09L Single"; add_description="http://www.alps.com/prod/info/E/HTML/Potentiometer/RotaryPotentiometers/RK09L/RK09L_list.html" pins = 3; rmx=2.5; rmy=2.5; ddrill=1; wbody=7.45; hbody=12.1; height3d = 6.5+0.25+4.85; screwzpos = 6.5+0.25; wscrew=5; dscrew=9 wshaft=15-wscrew; dshaft=6; pinxoffset=5; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(mh_ddrill=2.1, mh_count=2, mh_rmx=0, mh_rmy=9.5, mh_xoffset=-4.1, mh_yoffset=(9.5-2*rmy)/2.0, class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Alps RK09L Single" voffsetx=1; dbody=0; vwbody=11.35; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=6.5; c_offsety=hbody/2.0 makePotentiometerVertical(mh_ddrill=2, mh_count=2, mh_rmx=0, mh_rmy=9.5, mh_xoffset=7.5, mh_yoffset=(9.5-2*rmy)/2.0, shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Alps RK09L Double" pins = 6; wbody=9.14 makePotentiometerHorizontal(mh_ddrill=2.1, mh_count=2, mh_rmx=0, mh_rmy=9.5, mh_xoffset=-5.8, mh_yoffset=(9.5-2*rmy)/2.0, class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Alps RK09L Double" voffsetx=1; dbody=0; vwbody=11.35; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=6.5; c_offsety=hbody/2.0 makePotentiometerVertical(mh_ddrill=2, mh_count=2, mh_rmx=0, mh_rmy=9.5, mh_xoffset=7.5, mh_yoffset=(9.5-2*rmy)/2.0, shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=dscrew+0.5,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Alps RK09Y11 Single"; add_description="http://www.alps.com/prod/info/E/HTML/Potentiometer/RotaryPotentiometers/RK09Y11/RK09Y11_list.html" pins = 3; rmx=5.0; rmy=2.5; ddrill=1.0; wbody=5.4; hbody=9.5; height3d = 6.25+0.25+4.85; screwzpos = 6.25+0.25; wscrew=5; dscrew=7 wshaft=12-wscrew; dshaft=5; pinxoffset=3.45; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_pv,height3d=height3d, screwzpos=screwzpos) class_name="Bourns 3339S"; add_description='http://www.bourns.com/docs/Product-Datasheets/3339.pdf' pins = 3; rmx=-2.54; rmy=2.54; ddrill=0.8; wbody=5.97; hbody=8.13; dbody=0; height3d = 9.53; screwzpos = 5.54; wscrew=8-5.97; dscrew=7.62 wshaft=0; dshaft=4; pinxoffset=+4.57-wscrew; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) rmx=2.54; pinxoffset=+4.57-wscrew+2.54 class_name="Bourns 3339W" makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Bourns 3339P" pins = 3; rmx=-2.54; rmy=2.54; ddrill=0.7; wbody=0; hbody=7.62; dbody=7.62; height3d = 6.35; wscrew=-wbody; dscrew=5 wshaft=0; dshaft=0; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 voffsetx=-rmx; vwbody=0; pinyoffset=(hbody-2*rmy)/2.0; c_offsetx=rmx; c_offsety=hbody/2.0; c_ddrill=2 makePotentiometerVertical(screwstyle='slit', style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Bourns 3339H" rmx = 2.54 / math.sqrt(2); rmy = 2.54 / math.sqrt(2); voffsetx = rmx*2; vwbody = 0 pinyoffset = (hbody - 2 * rmy)/2.0; c_offsetx=-rmx; c_offsety=hbody/2.0; c_ddrill=2 makePotentiometerVertical(screwstyle='slit', style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Vishay T7-YA Single"; add_description="http://www.vishay.com/docs/51015/t7.pdf" pins = 3; rmx=2.54; rmy=2.54; ddrill=0.8; wbody=0; hbody=7; dbody=7; height3d = 5.85; wscrew=-wbody; dscrew=4.1 wshaft=0; dshaft=0; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 voffsetx=-rmx; vwbody=0; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=2.5; c_offsety=hbody/2.0; c_ddrill=2 makePotentiometerVertical(screwstyle='slit', style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Bourns 3386X"; add_description="https://www.bourns.com/pdfs/3386.pdf" pins = 3; rmx=2.54; rmy=2.54; ddrill=0.8; wbody=-4.83; hbody=9.53; dbody=0; height3d = 9.53; screwzpos = 5.33; wscrew=0; dscrew=3.15 wshaft=0; dshaft=0; pinxoffset=-(4.83-2.54)/2.0; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name = "Bourns 3386C" rmx=0; pinxoffset=-4.83/2.0 makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Bourns 3386P" rmx=2.54; dbody=0; voffsetx=-4.78; vwbody=9.53; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=9.53-5.64; c_offsety=hbody/2.0; c_ddrill=2; height3d = 4.83 makePotentiometerVertical(screwstyle="slit", style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Bourns 3386F" rmx=5.08; voffsetx=-9.53+5.08+2.34 makePotentiometerVertical(screwstyle="slit", style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Vishay T73XX"; add_description="http://www.vishay.com/docs/51016/t73.pdf" pins = 3; rmx=2.54; rmy=2.54; ddrill=0.8; wbody=-4.7; hbody=6.6; dbody=0; height3d = 7; screwzpos = 3.8; wscrew=0; dscrew=3 wshaft=0; dshaft=0; pinxoffset=-1.02; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Vishay T73XW" rmx=0; pinxoffset=-2.35 makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Vishay T73YP" rmx=2.54; dbody=0; voffsetx=-3.56; vwbody=7; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=3.8; c_offsety=hbody/2.0; c_ddrill=2 makePotentiometerVertical(screwstyle="cross", style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_ph_bel,height3d=height3d) class_name="Piher PT-6-H"; add_description="http://www.piher-nacesa.com/pdf/11-PT6v03.pdf" pins = 3; rmx=2.5; rmy=2.5; ddrill=0.9; wbody=-3.5; hbody=6.3; dbody=6.3; height3d = 4.5+dbody/2.0; screwzpos = 4.5; wscrew=-wbody; dscrew=2 wshaft=0; dshaft=1.8; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-6-V" rmx=5; dbody=6.3; voffsetx=0; vwbody=0; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=2.5; c_offsety=hbody/2.0; c_ddrill=2; height3d=4 makePotentiometerVertical(style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh,height3d=height3d) makePotentiometerVertical(style="trimmer", shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_bel,height3d=height3d) class_name="Piher PT-10-H01"; add_description="http://www.piher-nacesa.com/pdf/12-PT10v03.pdf" pins = 3; rmx=2.5; rmy=2.5; ddrill=1.3; wbody=-4.8; hbody=10.3; height3d = 12.1; screwzpos = 7; dbody=10.3; wscrew=-wbody; dscrew=3.5 wshaft=0; dshaft=3; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 #name_additions=["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2*rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-10-H05" rmx=5; height3d = 12.1; screwzpos = 7; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-101-H3.8" rmx=3.8; height3d = 17.1; screwzpos = 9.6; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] #makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-10-V10" hbody=10; rmx=10; dbody=10.3; voffsetx=0; vwbody=0; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=5; c_offsety=hbody/2.0; c_ddrill=4; height3d=5.3 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerVertical(style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh,height3d=height3d) makePotentiometerVertical(style="trimmer", shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_bel,height3d=height3d) class_name="Piher PT-10-V05" voffsetx = -5.3/2.0; hbody=10; rmx=5; dbody=10.3; vwbody=0; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=10.3/2.0; c_offsety=dbody/2.0; c_ddrill=3 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerVertical(style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_bel,height3d=height3d) #name_additions = [] class_name="Piher PT-15-H05"; add_description="http://www.piher-nacesa.com/pdf/14-PT15v03.pdf" pins = 3; rmx=5.0; rmy=5; ddrill=1.3; wbody=-5; hbody=15; height3d = 17.5; screwzpos = 10; dbody=15; wscrew=-wbody; dscrew=6 wshaft=0; dshaft=4.4; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-15-H01" rmy=5; rmx=2.5; height3d = 17.5; screwzpos = 10; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-15-H06" rmy=4.4; rmx=4; height3d = 17.1; screwzpos = 9.6; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-15-H25" rmy=5; rmx=5; height3d = 20; screwzpos = 12.5; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="Piher PT-15-V02" hbody=10; rmx=12.5; dbody=15; voffsetx=0; vwbody=0; vpinyoffset=(dbody-2*rmy)/2.0; c_offsetx=7.5; c_offsety=dbody/2.0; c_ddrill=7; height3d=5.5 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerVertical(style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh,height3d=height3d) makePotentiometerVertical(style="trimmer", shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_bel,height3d=height3d) class_name="Piher PT-15-V15" voffsetx =0; hbody=15; rmx=15; dbody=15; vwbody=0; vpinyoffset=(dbody-2*rmy)/2.0; c_offsetx=7.5; c_offsety=dbody/2.0; c_ddrill=7 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerVertical(style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh,height3d=height3d) makePotentiometerVertical(style="trimmer", shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_bel,height3d=height3d) #name_additions=[] class_name="ACP CA6-H2,5"; add_description="http://www.acptechnologies.com/wp-content/uploads/2017/06/01-ACP-CA6.pdf" pins = 3; rmx=2.5; rmy=2.5; ddrill=0.9; wbody=-3.5; hbody=6.3; dbody=0; height3d = 4.5+hbody/2.0; screwzpos = 4.5; wscrew=-wbody; dscrew=2 wshaft=0; dshaft=1.8; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="ACP CA9-H2,5"; add_description="http://www.acptechnologies.com/wp-content/uploads/2017/05/02-ACP-CA9-CE9.pdf" pins = 3; rmx=2.5; rmy=2.5; ddrill=1.3; wbody=-4.8; hbody=9.8; dbody=0; height3d = 12; screwzpos = 7; wscrew=-wbody; dscrew=3 wshaft=0; dshaft=2.1; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="ACP CA9-H3,8" rmx=3.8; height3d = 12 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="ACP CA9-H5" rmx=5; height3d = 12 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="ACP CA9-V10" rmx=10; dbody=0; voffsetx=0; vwbody=10; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=vwbody/2.0; c_offsety=hbody/2.0; c_ddrill=4; height3d=7.2 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerVertical(style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh,height3d=height3d) makePotentiometerVertical(style="trimmer", shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_bel,height3d=height3d) #name_additions=[] class_name="ACP CA14-H2,5"; add_description="http://www.acptechnologies.com/wp-content/uploads/2017/10/03-ACP-CA14-CE14.pdf" pins = 3; rmx=2.5; rmy=5; ddrill=1.3; wbody=-5.0; hbody=14; dbody=0; height3d = 17; screwzpos = 10; wscrew=-wbody; dscrew=6 wshaft=0; dshaft=5; pinxoffset=0; pinyoffset=(hbody-2*rmy)/2.0 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="ACP CA14-H4" rmx=4 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="ACP CA14-H5" rmx=5 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerHorizontal(style="trimmer", class_name=class_name, wbody=wbody, hbody=hbody, wscrew=wscrew, dscrew=dscrew, wshaft=wshaft, dshaft=dshaft, pinxoffset=pinxoffset,pinyoffset=pinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, R_POW=R_POW, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trv,height3d=height3d, screwzpos=screwzpos) class_name="ACP CA14V-15" rmx=15; dbody=0; voffsetx=0.5; vwbody=14; vpinyoffset=(hbody-2*rmy)/2.0; c_offsetx=vwbody/2.0; c_offsety=hbody/2.0; c_ddrill=7; height3d=7.2 #name_additions = ["Px{0:1.1f}mm_Py{1:1.1f}mm".format(rmx, 2 * rmy)] makePotentiometerVertical(style="trimmer", shaft_hole=False, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh,height3d=height3d) makePotentiometerVertical(style="trimmer", shaft_hole=True, class_name=class_name, wbody=vwbody, hbody=hbody, d_body=dbody, dshaft=dshaft, dscrew=dscrew, c_ddrill=c_ddrill,c_offsetx=c_offsetx, c_offsety=c_offsety, pinxoffset=voffsetx,pinyoffset=vpinyoffset, pins=pins, rmx=rmx, rmy=rmy, ddrill=ddrill, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_trh_bel,height3d=height3d) #name_additions=[] class_name="Bourns 3005"; add_description = "http://www.bourns.com/docs/Product-Datasheets/3005.pdf"; wbody=19.3; hbody=4.06; pinxoffset=16; pinyoffset=(hbody-2.54)/2.0+2.54; height3d = 7.87; rmx2=-7.62; rmy2=-2.54; rmx3=-12.7; rmy3=0; ddrill=1; dscrew=3; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody/2.0 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Vishay 43"; add_description = "http://www.vishay.com/docs/57026/43.pdf"; wbody=19.0; hbody=4.8; pinxoffset=16; pinyoffset=(hbody-2.54)/2.0+2.54; height3d = 6.35; rmx2=-7.62; rmy2=-2.54; rmx3=-12.7; rmy3=0; ddrill=1; dscrew=2.36; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody/2.0 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3006P"; add_description = "https://www.bourns.com/docs/Product-Datasheets/3006.pdf"; wbody=19.05; hbody=4.83; pinxoffset=16; pinyoffset=(hbody-2.54)/2.0+2.54; height3d = 6.35; rmx2=-7.62; rmy2=-2.54; rmx3=-12.7; rmy3=0; ddrill=1; dscrew=2.36; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody/2.0 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3006W" wbody=19.05; hbody=4.83; pinxoffset=16; pinyoffset=4.83+0.15; height3d = 6.35; rmx2=-7.62; rmy2=-5.06; rmx3=-12.7; rmy3=0; ddrill=1; dscrew=2.36; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody/2.0 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3006Y" wbody=19.05; hbody=4.83; pinxoffset=18.42; pinyoffset=(hbody-2.54)/2.0+2.54; height3d = 6.35; rmx2=-(17.78-7.62); rmy2=-2.54; rmx3=-17.78; rmy3=0; ddrill=1; dscrew=2.36; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody/2.0 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3009P"; add_description = "http://www.bourns.com/docs/Product-Datasheets/3009.pdf" wbody=19.05; hbody=4.83; pinxoffset=16; pinyoffset=(hbody-2.54)/2.0+2.54; height3d = 8.98; rmx2=-7.62; rmy2=-2.54; rmx3=-12.7; rmy3=0; ddrill=1; dscrew=2.36; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody/2.0 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3009Y" wbody=19.05; hbody=4.83; pinxoffset=18.42; pinyoffset=(hbody-2.54)/2.0+2.54; height3d = 8.98; rmx2=-(17.78-7.62); rmy2=-2.54; rmx3=-17.78; rmy3=0; ddrill=1; dscrew=2.36; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody/2.0 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3296W"; add_description = "https://www.bourns.com/pdfs/3296.pdf"; wbody=9.53; hbody=4.83; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=2.41; height3d = 10.03; rmx2=-2.54; rmy2=0; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=2.19; wscrew = dscrew; screwxoffset = wbody-1.27; screwyoffset = hbody-1.27 style = "screwtop"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst, height3d=height3d) class_name="Bourns 3296X" wbody=9.53; hbody=4.83; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=2.41; height3d = 10.03; rmx2=-2.54; rmy2=0; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew = 2.19; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody-1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3296Y" wbody=9.53; hbody=4.83; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=1.14; height3d = 10.03; rmx2=-2.54; rmy2=2.54; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=2.19; wscrew = dscrew; screwxoffset = wbody-1.27; screwyoffset = hbody-1.27 style = "screwtop"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst, height3d=height3d) class_name="Bourns 3296Z" wbody=9.53; hbody=4.83; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=hbody-1.14-2.54; height3d = 10.03; rmx2=-2.54; rmy2=2.54; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=2.19; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody-1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3296P" wbody=10.03; hbody=9.53; pinxoffset=wbody/2.0; pinyoffset=(hbody-5.08)/2.0; height3d = 4.83; rmx2=-2.54; rmy2=2.54; rmx3=0; rmy3=5.08; ddrill=0.8; dscrew=2.19; wscrew = 1.52; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3299W"; add_description = "https://www.bourns.com/pdfs/3299.pdf"; wbody=9.53; hbody=6.10; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=1.91; height3d = 10.03; rmx2=-2.54; rmy2=0; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=2.19; wscrew = dscrew; screwxoffset = wbody-1.27; screwyoffset = hbody-1.27 style = "screwtop"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst, height3d=height3d) class_name="Bourns 3299X" wbody=9.53; hbody=6.10; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=1.91; height3d = 10.03; rmx2=-2.54; rmy2=0; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew = 2.19; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody-1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3299Y" wbody=9.53; hbody=6.10; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=1.91; height3d = 10.03; rmx2=-2.54; rmy2=2.54; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=2.19; wscrew = dscrew; screwxoffset = wbody-1.27; screwyoffset = hbody-1.27 style = "screwtop"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst, height3d=height3d) class_name="Bourns 3299Z" wbody=9.53; hbody=6.10; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=1.91; height3d = 10.03; rmx2=-2.54; rmy2=2.54; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=2.19; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody-1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3299P" wbody=10.03; hbody=9.53; pinxoffset=wbody/2.0; pinyoffset=(hbody-5.08)/2.0; height3d = 6.10; rmx2=-2.54; rmy2=2.54; rmx3=0; rmy3=5.08; ddrill=0.8; dscrew=2.19; wscrew = 1.52; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3266Y"; add_description = "https://www.bourns.com/docs/Product-Datasheets/3266.pdf"; wbody=6.71; hbody=4.5; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=2.16; height3d = 6.71; rmx2=-2.54; rmy2=0; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=1.78; wscrew = dscrew; screwxoffset = wbody-1.22; screwyoffset = hbody-1.27 style = "screwtop"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst, height3d=height3d) class_name="Bourns 3266Z" wbody=6.71; hbody=4.5; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=2.16; height3d = 6.71; rmx2=-2.54; rmy2=0; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew = 1.78; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody-1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3266W" wbody=6.71; hbody=4.5; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=1.02; height3d = 6.71; rmx2=-2.54; rmy2=2.54; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=1.78; wscrew = dscrew; screwxoffset = wbody-1.27; screwyoffset = hbody-1.27 style = "screwtop"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tst, height3d=height3d) class_name="Bourns 3266X" wbody=6.71; hbody=4.5; pinxoffset=(wbody-5.08)/2.0+5.08; pinyoffset=1.02; height3d = 6.71; rmx2=-2.54; rmy2=2.54; rmx3=-5.08; rmy3=0; ddrill=0.8; dscrew=1.78; wscrew = 1.52; screwxoffset = 0; screwyoffset = hbody-1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) class_name="Bourns 3266P" wbody=6.71; hbody=6.71; pinxoffset=wbody/2.0; pinyoffset=(hbody-5.08)/2.0; height3d = 4.5; rmx2=-2.54; rmy2=2.54; rmx3=0; rmy3=5.08; ddrill=0.8; dscrew=1.78; wscrew = 1.52; screwxoffset = 0; screwyoffset = 1.27 style = "screwleft"; SMD_pads = False; SMD_padsize = [] makeSpindleTrimmer(shaft_hole=False, class_name=class_name, ddrill=ddrill, wbody=wbody, hbody=hbody, pinxoffset=pinxoffset, pinyoffset=pinyoffset, rmx2=rmx2, rmy2=rmy2, rmx3=rmx3, rmy3=rmy3, dscrew=dscrew, wscrew=wscrew, screwxoffset=screwxoffset, screwyoffset=screwyoffset, style=style, SMD_pads=SMD_pads, SMD_padsize=SMD_padsize, specialtags=[], add_description=add_description, name_additions=[], script3d=script3d_tsl, height3d=height3d) ================================================ FILE: scripts/Potentiometers/slide_Potentiometer.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) sys.path.append(os.path.join(sys.path[0], "..", "tools")) from KicadModTree import * from drawing_tools import * def slide_pot(args): footprint_name = args["name"] dimA = args["dimA"] dimB = args["dimB"] dimC = args["dimC"] dimD = args["dimD"] dimE = args["dimE"] travel = args["travel"] f = Footprint(footprint_name) f.setDescription("Bourns single-gang slide potentiometer, " + str(travel) + "mm travel, https://www.bourns.com/docs/Product-Datasheets/pta.pdf") f.setTags("Bourns single-gang slide potentiometer " + str(travel) + "mm") f.append(Model(filename="${KISYS3DMOD}/Potentiometer_THT.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) dPin = [1.2, 1.2] dMP = [1.7, 1.7] pPin = [1.75, 1.75] pMP = [2.7, 2.7] s = [1.0, 1.0] t = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 silk = wSilkS silkGap = 2 * wSilkS silk_ko = 0.3 crtYd = 0.5 xCenter = dimE / 2 yCenter = 3.5 / 2 xPin1 = 0.0 yPin1 = 0.0 xPin2 = 0.0 yPin2 = 3.5 xPin3 = dimE yPin3 = 0.0 mountingPins = [] for row in [[-1, dimC], [1, dimD]]: y = yCenter + 8.4 / 2 * row[0] half = row[1] / 2 mountingPins.append([xCenter - half, y]) mountingPins.append([xCenter + half, y]) halfWidth = dimA / 2 halfHeight = 9.0 / 2 xLeftFab = xCenter - halfWidth xRightFab = xCenter + halfWidth yTopFab = yCenter - halfHeight yBottomFab = yCenter + halfHeight xLeftSilk = xLeftFab - silk xRightSilk = xRightFab + silk yTopSilk = yTopFab - silk yBottomSilk = yBottomFab + silk xLeftCrtYd = xLeftFab - crtYd xRightCrtYd = xRightFab + crtYd yTopCrtYd = yTopFab - crtYd yBottomCrtYd = yBottomFab + crtYd yRef = yTopFab - 1.25 yValue = yBottomFab + 1.25 yFabRef = yCenter hTravel = travel / 2 xLeftTravel = xCenter - hTravel xRightTravel = xCenter + hTravel keepouts = [] # Pins for pin in [["1", [xPin1, yPin1], Pad.SHAPE_RECT], ["2", [xPin2, yPin2], Pad.SHAPE_CIRCLE], ["3", [xPin3, yPin3], Pad.SHAPE_CIRCLE]]: f.append(Pad(number=pin[0], type=Pad.TYPE_THT, shape=pin[2], at=pin[1], size=pPin, layers=Pad.LAYERS_THT, drill=dPin)) x = pin[1][0] y = pin[1][1] d = pPin[0] + 2 * silk_ko if pin[0] == "1": keepouts = keepouts + addKeepoutRect(x, y, d, d) else: keepouts = keepouts + addKeepoutRound(x, y, d, d) for mp in mountingPins: f.append(Pad(number="MP", type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=mp, size=pMP, layers=Pad.LAYERS_THT, drill=dMP)) d = pMP[0] + 2 * silk_ko keepouts = keepouts + addKeepoutRound(mp[0], mp[1], d, d) # Text f.append(Text(type="reference", text="REF**", at=[xCenter, yRef], layer="F.SilkS", size=s, thickness=t)) f.append(Text(type="value", text=footprint_name, at=[xCenter, yValue], layer="F.Fab", size=s, thickness=t)) f.append(Text(type="user", text="%R", at=[xCenter, yFabRef], layer="F.Fab", size=s, thickness=t)) # Fab f.append(PolygoneLine(polygone=[[xLeftFab + 1, yTopFab], [xRightFab, yTopFab], [xRightFab, yBottomFab], [xLeftFab, yBottomFab], [xLeftFab, yTopFab + 1], [xLeftFab + 1, yTopFab]], layer="F.Fab", width=wFab)) for dir in [-1, 1]: xScrew = xCenter + dir * (dimB / 2) f.append(Circle(center=[xScrew, yCenter], radius=1.0, layer="F.Fab", width=wFab)) # Silk outline addRectWithKeepout(f, xLeftSilk, yTopSilk, xRightSilk - xLeftSilk, yBottomSilk - yTopSilk, "F.SilkS", wSilkS, keepouts) # Silk pin 1 indicator xp1 = -(pPin[0] / 2 + silk_ko) yp1 = 0.0 f.append(PolygoneLine(polygone=[[xp1, yp1], [xp1 - 0.5, yp1 - 0.5], [xp1 - 0.5, yp1 + 0.5], [xp1, yp1]], layer="F.SilkS", width=wSilkS)) # Silk travel indicator f.append(Line(start=[xLeftTravel, yCenter], end=[xRightTravel, yCenter], layer="F.SilkS", width=wSilkS)) for dir in [-1, 1]: xTravel = xCenter + dir * hTravel xArrow = xCenter + dir * (hTravel - 0.75) f.append(Line(start=[xTravel, yCenter - 1.5], end=[xTravel, yCenter + 1.5], layer="F.SilkS", width=wSilkS)) f.append(PolygoneLine(polygone=[[xArrow, yCenter - 0.75], [xTravel, yCenter], [xArrow, yCenter + 0.75]], layer="F.SilkS", width=wSilkS)) # CrtYd f.append(RectLine(start=[xLeftCrtYd, yTopCrtYd], end=[xRightCrtYd, yBottomCrtYd], layer="F.CrtYd", width=wCrtYd)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(slide_pot) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("dimA", type=float, required=True) parser.add_parameter("dimB", type=float, required=True) parser.add_parameter("dimC", type=float, required=True) parser.add_parameter("dimD", type=float, required=True) parser.add_parameter("dimE", type=float, required=True) parser.add_parameter("travel", type=float, required=True) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Potentiometers/slide_Potentiometer.yaml ================================================ Potentiometer_Bourns_PTA1543_Single_Slide: dimA: 30 dimB: 26 dimC: 17.8 dimD: 20.2 dimE: 28.5 travel: 15 Potentiometer_Bourns_PTA2043_Single_Slide: dimA: 35 dimB: 31 dimC: 22.8 dimD: 25.2 dimE: 33 travel: 20 Potentiometer_Bourns_PTA3043_Single_Slide: dimA: 45 dimB: 41 dimC: 32.8 dimD: 35.2 dimE: 43.5 travel: 30 Potentiometer_Bourns_PTA4543_Single_Slide: dimA: 60 dimB: 56 dimC: 47.8 dimD: 50.2 dimE: 58.5 travel: 45 Potentiometer_Bourns_PTA6043_Single_Slide: dimA: 75 dimB: 71 dimC: 62.8 dimD: 65.2 dimE: 73.5 travel: 60 ================================================ FILE: scripts/Recom_DCDC/Recom_SIP.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_sip import * rm=2.54 def recom_78_3pin(): pins=3 ddrill_large=1.2 pad_large=[1.7, 2.5] ddrill_small=1.0 pad_small=[1.5, 2.3] package_size=[11.5,8.5,17.5] left_offset=3.21 top_offset=2 makeSIPVertical(pins=pins, rm=rm, ddrill=ddrill_large, pad=pad_large, package_size=package_size, left_offset=left_offset, top_offset=top_offset, footprint_name='Converter_DCDC_RECOM_R-78B-2.0_THT', description="DCDC-Converter, RECOM, RECOM_R-78B-2.0, SIP-{0}, pitch {1:3.2f}mm, package size {2}x{3}x{4}mm^3, https://www.recom-power.com/pdf/Innoline/R-78Bxx-2.0.pdf".format(pins,rm,package_size[0],package_size[1],package_size[2]), tags="dc-dc recom buck sip-{0} pitch {1:3.2f}mm".format(pins,rm), lib_name='Converter_DCDC') package_size=[11.6,8.5,10.4] left_offset=package_size[0]-3.21-5.08 top_offset=package_size[1]-2 makeSIPVertical(pins=pins, rm=rm, ddrill=ddrill_small, pad=pad_small, package_size=package_size, left_offset=left_offset, top_offset=top_offset, footprint_name='Converter_DCDC_RECOM_R-78E-0.5_THT', description="DCDC-Converter, RECOM, RECOM_R-78E-0.5, SIP-{0}, pitch {1:3.2f}mm, package size {2}x{3}x{4}mm^3, https://www.recom-power.com/pdf/Innoline/R-78Exx-0.5.pdf".format(pins,rm,package_size[0],package_size[1],package_size[2]), tags="dc-dc recom buck sip-{0} pitch {1:3.2f}mm".format(pins,rm), lib_name='Converter_DCDC') package_size=[11.5,8.5,17.5] left_offset=3.21 top_offset=2 pin_bottom_offset=1.5 makeSIPVertical(pins=pins, rm=rm, ddrill=ddrill_small, pad=pad_small, package_size=package_size, left_offset=left_offset, top_offset=top_offset, footprint_name='Converter_DCDC_RECOM_R-78HB-0.5_THT', description="DCDC-Converter, RECOM, RECOM_R-78HB-0.5, SIP-{0}, pitch {1:3.2f}mm, package size {2}x{3}x{4}mm^3, https://www.recom-power.com/pdf/Innoline/R-78HBxx-0.5_L.pdf".format(pins,rm,package_size[0],package_size[1],package_size[2]), tags="dc-dc recom buck sip-{0} pitch {1:3.2f}mm".format(pins,rm), lib_name='Converter_DCDC') makeSIPHorizontal(pins=pins, rm=rm, ddrill=ddrill_small, pad=pad_small, package_size=package_size, left_offset=left_offset, pin_bottom_offset=pin_bottom_offset, footprint_name='Converter_DCDC_RECOM_R-78HB-0.5L_THT', description="DCDC-Converter, RECOM, RECOM_R-78HB-0.5L, SIP-{0}, Horizontally Mounted, pitch {1:3.2f}mm, package size {2}x{3}x{4}mm^3, https://www.recom-power.com/pdf/Innoline/R-78HBxx-0.5_L.pdf".format(pins,rm,package_size[0],package_size[1],package_size[2]), tags="dc-dc recom buck sip-{0} pitch {1:3.2f}mm".format(pins,rm), lib_name='Converter_DCDC') def recom_78_4pin(): pins=4 ddrill=1.0 pad=[1.5, 2.3] package_size=[11.6,8.5,10.4] left_offset=2 top_offset=package_size[1]-2 makeSIPVertical(pins=pins, rm=rm, ddrill=ddrill, pad=pad, package_size=package_size, left_offset=left_offset, top_offset=top_offset, footprint_name='Converter_DCDC_RECOM_R-78S-0.1_THT', description="DCDC-Converter, RECOM, RECOM_R-78S-0.1, SIP-{0}, pitch {1:3.2f}mm, package size {2}x{3}x{4}mm^3, https://www.recom-power.com/pdf/Innoline/R-78Sxx-0.1.pdf".format(pins,rm,package_size[0],package_size[1],package_size[2]), tags="dc-dc recom buck sip-{0} pitch {1:3.2f}mm".format(pins,rm), lib_name='Converter_DCDC') def recom_r5(): pins=12 ddrill=1.0 pad=[1.5, 2.3] package_size=[32.2,9.1,15] left_offset=2.1 top_offset=0.8 pin_bottom_offset=2 makeSIPVertical(pins=pins, rm=rm, ddrill=ddrill, pad=pad, package_size=package_size, left_offset=left_offset, top_offset=top_offset, footprint_name='Converter_DCDC_RECOM_R5xxxPA_THT', description="DCDC-Converter, RECOM, RECOM_R5xxxPA, SIP-{0}, pitch {1:3.2f}mm, package size {2}x{3}x{4}mm^3, https://www.recom-power.com/pdf/Innoline/R-5xxxPA_DA.pdf".format(pins,rm,package_size[0],package_size[1],package_size[2]), tags="dc-dc recom buck sip-{0} pitch {1:3.2f}mm".format(pins,rm), lib_name='Converter_DCDC') makeSIPHorizontal(pins=pins, rm=rm, ddrill=ddrill, pad=pad, package_size=package_size, left_offset=left_offset, pin_bottom_offset=pin_bottom_offset, footprint_name='Converter_DCDC_RECOM_R5xxxDA_THT', description="DCDC-Converter, RECOM, RECOM_R5xxxDA, SIP-{0}, Horizontally Mounted, pitch {1:3.2f}mm, package size {2}x{3}x{4}mm^3, https://www.recom-power.com/pdf/Innoline/R-5xxxPA_DA.pdf".format(pins,rm,package_size[0],package_size[1],package_size[2]), tags="dc-dc recom buck sip-{0} pitch {1:3.2f}mm".format(pins,rm), lib_name='Converter_DCDC') if __name__ == '__main__': recom_78_3pin() recom_78_4pin() recom_r5() ================================================ FILE: scripts/ResistorArrays_SIP_THT/make_Resistor_array_SIP.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_sip import * if __name__ == '__main__': for R in range(3, 14): pins=R+1 makeResistorSIP(pins, "Resistor_Array_SIP%d" % (pins), "{0}-pin Resistor SIP pack".format(pins, R)) #for R in range(3,6): # pins=2*R # makeResistorSIP(pins, "Resistor_ArrayParallel_SIP%d" % (R), "{0}-pin Resistor SIP pack, {1} parallel resistors".format(pins, R)) #for R in range(3,6): # pins=R+2 # makeResistorSIP(pins, "Resistor_ArrayDivider_SIP%d" % (R), "{0}-pin Resistor SIP pack, {1} voltage dividers = {2} resistors".format(pins, R, 2*R)) ================================================ FILE: scripts/Resistor_THT/make_Resistors_THT.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_scripts_resistorlike import * if __name__ == '__main__': lib_name="${KISYS3DMOD}/Resistor_THT" # standard resistors: http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf type = "cyl" script3d="res_axial_cyl_hor.py" with open(script3d, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dv="res_axial_cyl_ver.py" with open(script3dv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") d2=0 seriesname = "Axial_DIN0204"; w=3.6; d=1.6; ddrill=0.7; R_POW=1.0/6.0; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf"; name_additions=[] for rm in [5.08, 7.62]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [1.9,2.54, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0207"; w = 6.3; d = 2.5; ddrill = 0.8; R_POW = 0.25; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf"; name_additions=[] for rm in [7.62, 10.16, 15.24]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [2.54, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname="Axial_DIN0309"; w = 9; d = 3.2; ddrill = 0.8; R_POW = 0.5; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf"; name_additions=[] for rm in [12.7, 15.24, 20.32, 25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [2.54, 5.08]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0411"; w = 9.9; d = 3.6; ddrill = 1.2; R_POW = 1; add_description=""; name_additions=[] for rm in [12.7,15.24, 20.32, 25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0414"; w = 11.9; d = 4.5; ddrill = 1.2; R_POW = 2; add_description="http://www.vishay.com/docs/20128/wkxwrx.pdf"; name_additions=[] for rm in [15.24, 20.32, 25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0516"; w = 15.5; d = 5; ddrill = 1.2; R_POW = 2; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf"; name_additions=[] for rm in [20.32, 25.4, 30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [5.08, 7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0614"; w = 14.3; d = 5.7; ddrill = 1.4; R_POW = 1.5; add_description="" for rm in [15.24, 20.32, 25.4]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0617"; w = 17; d = 6; ddrill = 1.2; R_POW = 2; add_description="http://www.vishay.com/docs/20128/wkxwrx.pdf"; name_additions=[] for rm in [20.32, 25.4, 30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [5.08, 7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0918"; w = 18; d = 9; ddrill = 1.2; R_POW = 4; add_description="" for rm in [22.86, 25.4, 30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_DIN0922"; w = 20; d = 9; ddrill = 1.2; R_POW = 5; add_description="http://www.vishay.com/docs/20128/wkxwrx.pdf"; name_additions=[] for rm in [25.4, 30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) # POWER Resistors (rectangular) script3d = "res_axial_box_hor.py" with open(script3d, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") script3dv = "res_axial_box_ver.py" with open(script3dv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") type = "box" seriesname = "Axial_Power"; w=20; d=6.4; d2=6.4; ddrill=1.2; R_POW=4; add_description="http://cdn-reichelt.de/documents/datenblatt/B400/5WAXIAL_9WAXIAL_11WAXIAL_17WAXIAL%23YAG.pdf"; name_additions=[] for rm in [22.4, 25.4, 30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [5.08,7.62]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_Power"; w=25; d=6.4; d2=6.4; ddrill=1.2; R_POW=5; name_additions=[] for rm in [27.94,30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) seriesname = "Axial_Power"; w=38; d=6.4; d2=6.4; ddrill=1.2; R_POW=7; name_additions=[] for rm in [40.64,45.72]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) seriesname = "Axial_Power"; w=25; d=9; d2=9; ddrill=1.2; R_POW=7; name_additions=[] for rm in [27.94,30.48]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [7.62,10.16]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_Power"; w=38; d=9; d2=9; ddrill=1.2; R_POW=9; name_additions=[] for rm in [40.64,45.72]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) seriesname = "Axial_Power"; w=50; d=9; d2=9; ddrill=1.2; R_POW=11; name_additions=[] for rm in [55.88,60.96]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) seriesname = "Axial_Power"; w=75; d=9; d2=9; ddrill=1.2; R_POW=17; name_additions=[] for rm in [81.28,86.36]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) seriesname = "Axial_Power"; w=48; d=12.5; d2=12.5; ddrill=1.2; R_POW=15; name_additions=[] for rm in [55.88,60.96]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [7.62,10.16]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) seriesname = "Axial_Power"; w=60; d=14; d2=14; ddrill=1.2; R_POW=25; name_additions=[] for rm in [66.04,71.12]: makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3d, lib_name=lib_name) for rm in [10.16]: makeResistorAxialVertical(seriesname=seriesname, rm=rm, rmdisp=rm, l=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type, d2=d2, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", largepadsx=0, largepadsy=0, add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) # shunt resistor with additional pins script3dv = "res_axial_shunt_ver.py" with open(script3dv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") type = "box" seriesname = "Axial_Shunt"; ddrill=1.5; add_description="http://www.vishay.com/docs/30217/cpsl.pdf"; name_additions=[] rm = 25.4; shuntPinsRM=14.3; w=22.2; d=8; d2=d; R_POW=3 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, hasShuntPins=True, shuntPinsRM=shuntPinsRM, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) rm = 25.4; shuntPinsRM=14.3; w=22.2; d=9.5; d2=d; R_POW=5 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, hasShuntPins=True, shuntPinsRM=shuntPinsRM, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) rm = 38.1; shuntPinsRM=25.4; w=35.3; d=9.5; d2=d; R_POW=7 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, hasShuntPins=True, shuntPinsRM=shuntPinsRM, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) rm = 50.8; shuntPinsRM=34.93; w=47.6; d=9.5; d2=d; R_POW=10 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, hasShuntPins=True, shuntPinsRM=shuntPinsRM, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) rm = 50.8; shuntPinsRM=34.93; w=47.6; d=12.7; d2=d; R_POW=15 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, hasShuntPins=True, shuntPinsRM=shuntPinsRM, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[],script3d=script3dv, lib_name=lib_name) # wire bridge/bare metal resistor elements type = "bridge" seriesname = "Bare_Metal_Element"; d=4.8; d2=2; ddrill=1.5; add_description="https://www.bourns.com/pdfs/PWR4412-2S.pdf"; name_additions=[] rm = 11.4; w=rm+1; R_POW=1 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[], lib_name=lib_name) rm = 15.3; w=rm+1; R_POW=3 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[], lib_name=lib_name) rm = 20.3; w=rm+1; R_POW=5 makeResistorAxialHorizontal(seriesname=seriesname, rm=rm, rmdisp=rm, w=w, d=d, ddrill=ddrill, R_POW=R_POW, type=type,d2=d2, x_3d=[0,0,0], s_3d=[1,1,1], has3d=1, specialfpname="", add_description=add_description, name_additions=name_additions, specialtags=[], lib_name=lib_name) # radial resistors, 45deg wires script3dv = "res_radial_power_ver.py" with open(script3dv, "w") as myfile: myfile.write("#\n# SCRIPT to generate 3D models\n#\n\n") rm2=0; w2=0 type = "simple45"; seriesname = "Radial_Power"; add_description = "http://www.vitrohm.com/content/files/vitrohm_series_kv_-_201601.pdf"; name_additions=[] w = 7; h = 8; ddrill = 1.2; rm=2.4; rm2=2.3; R_POW=7 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=38, lib_name=lib_name) w = 9; h = 10; ddrill = 1.2; rm=2.7; rm2=2.3; R_POW=17 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=75, lib_name=lib_name) # radial resistors, simple box rm2=0; w2=0 type = "simple"; seriesname = "Box"; add_description = "http://www.vishay.com/docs/60051/cns020.pdf"; name_additions=[] w = 8.38; h = 2.54; ddrill = 0.8; rm=5.08; rm2=0; R_POW=0.5 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=6.62, lib_name=lib_name) add_description = "http://www.produktinfo.conrad.com/datenblaetter/425000-449999/443860-da-01-de-METALLBAND_WIDERSTAND_0_1_OHM_5W_5Pr.pdf"; name_additions=[] w = 13.0; h = 4.0; ddrill = 1.0; rm=9.0; rm2=0; R_POW=2 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=8, lib_name=lib_name) w = 14.0; h = 5.0; ddrill = 1.0; rm=9.0; rm2=0; R_POW=5 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=18, lib_name=lib_name) w = 26.0; h = 5.0; ddrill = 1.4; rm=20; rm2=0; R_POW=10 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=False, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=18, lib_name=lib_name) # radial resistors, simple rm2=0; w2=0 type = "simple"; seriesname = "Radial_Power"; add_description = "http://www.vishay.com/docs/30218/cpcx.pdf"; name_additions=[] w = 11.0; w2=w-2.0; h = 7.0; ddrill = 1.2; rm=5.0; rm2=0; R_POW=2 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=True, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=20.5, lib_name=lib_name) w = 12.0; w2=w-2.0; h = 8.0; ddrill = 1.2; rm=5.0; rm2=0; R_POW=3 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=True, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=24.99, lib_name=lib_name) w = 13.0; w2=w-2.0; h = 9.0; ddrill = 1.2; rm=5.0; rm2=0; R_POW=7 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=True, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=39, lib_name=lib_name) w = 16.1; w2=w-3; h = 9; ddrill = 1.4; rm=7.37; rm2=0; R_POW=10 makeResistorRadial(seriesname=seriesname, rm=rm, w=w, h=h, ddrill=ddrill, R_POW=R_POW, rm2=rm2, vlines=True, w2=w2, type=type, x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", name_additions=name_additions, specialtags=[], add_description=add_description,script3d=script3dv,height3d=34.85, lib_name=lib_name) ================================================ FILE: scripts/Resistors_SMD/README.md ================================================ ## HowTo generate the footprints ```bash mkdir Resistors_SMD.pretty cd Resistors_SMD.pretty ../../general/smd_chip.py ../smd_chip_resistors_smd.csv ``` ================================================ FILE: scripts/Resistors_SMD/generator found under SMD_chip_package_rlc-etc ================================================ ================================================ FILE: scripts/Resistors_SMD/smd_chip_resistors_smd.csv ================================================ name,description,tags,model_dir,courtyard,part_x,part_y,pad_x,pad_y,pad_spacing R_01005,Resistor SMD 01005,resistor 01005,Resistors_SMD,0.15,0.4,0.2,,, R_0201,Resistor SMD 0201,resistor 0201,Resistors_SMD,0.15,0.6,0.3,0.3,0.4,0.25 R_0402,Resistor SMD 0402,resistor 0402,Resistors_SMD,0.15,1,0.5,0.4,0.6,0.5 R_0504,Resistor SMD 0504,resistor 0504,Resistors_SMD,0.15,1.27,1.02,,, R_0603,Resistor SMD 0603,resistor 0603,Resistors_SMD,0.25,1.6,0.8,0.5,0.9,1 R_0805,Resistor SMD 0805,resistor 0805,Resistors_SMD,0.25,2,1.25,0.7,1.3,1.2 R_0907,Resistor SMD 0907,resistor 0907,Resistors_SMD,0.25,2.29,1.78,,, R_1008,Resistor SMD 1008,resistor 1008,Resistors_SMD,0.25,2.5,2,,, R_1206,Resistor SMD 1206,resistor 1206,Resistors_SMD,0.25,3.2,1.6,0.9,1.7,2 R_1210,Resistor SMD 1210,resistor 1210,Resistors_SMD,0.25,3.2,2.5,0.9,2.5,2 R_1218,Resistor SMD 1218,resistor 1218,Resistors_SMD,0.25,3.2,4.6,1,4.9,2 R_1411,Resistor SMD 1411,resistor 1411,Resistors_SMD,0.25,3.5,2.8,,, R_1515,Resistor SMD 1515,resistor 1515,Resistors_SMD,0.25,3.81,3.81,,, R_1608,Resistor SMD 1608,resistor 1608,Resistors_SMD,0.25,4,2,,, R_1806,Resistor SMD 1806,resistor 1806,Resistors_SMD,0.25,4.5,1.6,,, R_1812,Resistor SMD 1812,resistor 1812,Resistors_SMD,0.25,4.5,3.2,1.6,3.5,3.3 R_1825,Resistor SMD 1825,resistor 1825,Resistors_SMD,0.25,4.5,6.4,,, R_2010,Resistor SMD 2010,resistor 2010,Resistors_SMD,0.25,5,2.5,1,2.5,4 R_2220,Resistor SMD 2220,resistor 2220,Resistors_SMD,0.25,5.7,5,,, R_2312,Resistor SMD 2312,resistor 2312,Resistors_SMD,0.25,6,3.2,,, R_2512,Resistor SMD 2512,resistor 2512,Resistors_SMD,0.25,6.3,3.2,,, R_2515,Resistor SMD 2515,resistor 2515,Resistors_SMD,0.25,6.3,3.81,,, R_2716,Resistor SMD 2716,resistor 2716,Resistors_SMD,0.25,7,4,,, R_2824,Resistor SMD 2824,resistor 2824,Resistors_SMD,0.25,7.2,6.1,,, R_2917,Resistor SMD 2917,resistor 2917,Resistors_SMD,0.25,7.3,4.3,,, R_2920,Resistor SMD 2920,resistor 2920,Resistors_SMD,0.25,7.4,5,,, R_3111,Resistor SMD 3111,resistor 3111,Resistors_SMD,0.25,8,2.8,,, R_3931,Resistor SMD 3931,resistor 3931,Resistors_SMD,0.25,10,8,,, R_4018,Resistor SMD 4018,resistor 4018,Resistors_SMD,0.25,10.2,4.6,,, R_4020,Resistor SMD 4020,Resistor 4020,Resistors_SMD,0.25,10.2,5,,, R_4040,Resistor SMD 4040,resistor 4040,Resistors_SMD,0.25,10.2,10.2,,, R_4320,Resistor SMD 4320,resistor 4320,Resistors_SMD,0.25,11,5,,, R_4335,Resistor SMD 4335,resistor 4335,Resistors_SMD,0.25,11,9,,, R_4349,Resistor SMD 4349,resistor 4349,Resistors_SMD,0.25,11,12.5,,, R_4424,Resistor SMD 4424,resistor 4424,Resistors_SMD,0.25,11.11,6.1,,, R_4527,Resistor SMD 4527,resistor 4527,Resistors_SMD,0.25,11.5,7,,, R_4540,Resistor SMD 4540,resistor 4540,Resistors_SMD,0.25,11.4,10.2,,, R_4723,Resistor SMD 4723,resistor 4723,Resistors_SMD,0.25,12,6.1,,, R_4825,Resistor SMD 4825,resistor 4825,Resistors_SMD,0.25,12.2,6.35,,, R_5550,Resistor SMD 5550,resistor 5550,Resistors_SMD,0.25,14,12.7,,, R_5727,Resistor SMD 5727,resistor 5727,Resistors_SMD,0.25,14.4,7,,, R_6145,Resistor SMD 6145,resistor 6145,Resistors_SMD,0.25,15.5,11.5,,, R_6561,Resistor SMD 6561,resistor 6561,Resistors_SMD,0.25,16.5,15.5,,, R_7565,Resistor SMD 7565,resistor 7565,Resistors_SMD,0.25,19.1,16.5,,, ================================================ FILE: scripts/SMD_chip_package_rlc-etc/SMD_chip_devices.yaml ================================================ resistor: fp_lib_name: 'Resistor_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_wide_body_chip_resistor.yaml', 'size_resistor.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'R' description: 'Resistor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'resistor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" resistor_smaller_0603: fp_lib_name: 'Resistor_SMD' size_definitions: ['size_default_chip_devices_smaller_0603.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'R' description: 'Resistor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'resistor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" resistor_smaller_0402: fp_lib_name: 'Resistor_SMD' size_definitions: ['size_default_chip_devices_smaller_0402.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'R' description: 'Resistor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'resistor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" paste_pad: all_sides_rel: 0.9 #-10% heel_abs: -0.05 # additional heel reduction resistor_handsolder: #ToDo: only generate > 0402 fp_lib_name: 'Resistor_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_wide_body_chip_resistor.yaml', 'size_resistor.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'R' description: 'Resistor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal with elongated pad for handsoldering. {size_info:s}, generated with kicad-footprint-generator' keywords: 'resistor handsolder' ipc_density: 'nominal' pad_length_addition: 0.35 suffix: "_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder" include_suffix_in_3dpath: 'False' ###################################################################################### capacitor: fp_lib_name: 'Capacitor_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_capacitor_chip_devices.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'C' description: 'Capacitor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'capacitor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" capacitor_smaller_0603: fp_lib_name: 'Capacitor_SMD' size_definitions: ['size_default_chip_devices_smaller_0603.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'C' description: 'Capacitor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'capacitor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" capacitor_smaller_0402: fp_lib_name: 'Capacitor_SMD' size_definitions: ['size_default_chip_devices_smaller_0402.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'C' description: 'Capacitor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'capacitor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" paste_pad: all_sides_rel: 0.9 #-10% heel_abs: -0.05 # additional heel reduction capacitor_handsolder: #ToDo: only generate > 0402 fp_lib_name: 'Capacitor_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_capacitor_chip_devices.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'C' description: 'Capacitor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal with elongated pad for handsoldering. {size_info:s}, generated with kicad-footprint-generator' keywords: 'capacitor handsolder' ipc_density: 'nominal' pad_length_addition: 0.35 suffix: "_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder" include_suffix_in_3dpath: 'False' capacitor_tantal: fp_lib_name: 'Capacitor_Tantalum_SMD' size_definitions: ['size_tantal.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'CP' description: 'Tantalum Capacitor SMD {code_letter:s} ({code_metric:s} Metric), IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'capacitor tantalum' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" polarization_mark: 'True' capacitor_tantal_handsolder: fp_lib_name: 'Capacitor_Tantalum_SMD' size_definitions: ['size_tantal.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'CP' description: 'Tantalum Capacitor SMD {code_letter:s} ({code_metric:s} Metric), IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'capacitor tantalum' ipc_density: 'nominal' pad_length_addition: 0.35 suffix: "_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder" include_suffix_in_3dpath: 'False' polarization_mark: 'True' ###################################################################################### inductor: fp_lib_name: 'Inductor_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_inductor.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'L' description: 'Inductor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'inductor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" inductor_smaller_0603: fp_lib_name: 'Inductor_SMD' size_definitions: ['size_default_chip_devices_smaller_0603.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'L' description: 'Inductor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'inductor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" inductor_smaller_0402: fp_lib_name: 'Inductor_SMD' size_definitions: ['size_default_chip_devices_smaller_0402.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'L' description: 'Inductor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'inductor' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" paste_pad: all_sides_rel: 0.9 #-10% heel_abs: -0.05 # additional heel reduction inductor_handsolder: #ToDo: only generate > 0402 fp_lib_name: 'Inductor_SMD' size_definitions: ['size_default_chip_devices.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'L' description: 'Capacitor SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal with elongated pad for handsoldering. {size_info:s}, generated with kicad-footprint-generator' keywords: 'inductor handsolder' ipc_density: 'nominal' pad_length_addition: 0.35 suffix: "_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder" include_suffix_in_3dpath: 'False' ###################################################################################### diode: fp_lib_name: 'Diode_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_diode.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'D' description: 'Diode SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'diode' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "" diode_smaller_0603: fp_lib_name: 'Diode_SMD' size_definitions: ['size_default_chip_devices_smaller_0603.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'D' description: 'Diode SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'diode' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "" diode_smaller_0402: fp_lib_name: 'Diode_SMD' size_definitions: ['size_default_chip_devices_smaller_0402.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'D' description: 'Diode SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'diode' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "" paste_pad: all_sides_rel: 0.9 #-10% heel_abs: -0.05 # additional heel reduction diode_handsolder: fp_lib_name: 'Diode_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_diode.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'D' description: 'Diode SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'diode handsolder' ipc_density: 'nominal' pad_length_addition: 0.35 polarization_mark: 'True' suffix: "_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder" include_suffix_in_3dpath: 'False' diode_castellated: fp_lib_name: 'Diode_SMD' size_definitions: ['size_default_chip_devices.yaml', 'size_diode.yaml'] ipc_reference: "ipc_spec_castellated" prefix: 'D' description: 'Diode SMD {code_imperial:s} ({code_metric:s} Metric), castellated end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'diode castellated' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "_Castellated" ###################################################################################### led: fp_lib_name: 'LED_SMD' size_definitions: ['size_default_chip_devices.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'LED' description: 'LED SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'diode' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "" led_smaller_0603: fp_lib_name: 'LED_SMD' size_definitions: ['size_default_chip_devices_smaller_0603.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'LED' description: 'LED SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'LED' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "" led_smaller_0402: fp_lib_name: 'LED_SMD' size_definitions: ['size_default_chip_devices_smaller_0402.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'LED' description: 'LED SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'LED' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "" paste_pad: all_sides_rel: 0.9 #-10% heel_abs: -0.05 # additional heel reduction led_handsolder: fp_lib_name: 'LED_SMD' size_definitions: ['size_default_chip_devices.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'LED' description: 'LED SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'LED handsolder' ipc_density: 'nominal' pad_length_addition: 0.35 polarization_mark: 'True' suffix: "_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder" include_suffix_in_3dpath: 'False' led_castellated: fp_lib_name: 'LED_SMD' size_definitions: ['size_default_chip_devices.yaml'] ipc_reference: "ipc_spec_castellated" prefix: 'LED' description: 'LED SMD {code_imperial:s} ({code_metric:s} Metric), castellated end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'LED castellated' ipc_density: 'nominal' pad_length_addition: 0 polarization_mark: 'True' suffix: "_Castellated" ############################################################################### fuse: fp_lib_name: 'Fuse' size_definitions: ['size_default_chip_devices.yaml', 'size_fuse.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'Fuse' description: 'Fuse SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'fuse' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" fuse_smaller_0603: fp_lib_name: 'Fuse' size_definitions: ['size_default_chip_devices_smaller_0603.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'Fuse' description: 'Fuse SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'fuse' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" fuse_smaller_0402: fp_lib_name: 'Fuse' size_definitions: ['size_default_chip_devices_smaller_0402.yaml'] ipc_reference: "ipc_spec_smaller_0603" prefix: 'Fuse' description: 'Fuse SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal, {size_info:s}, generated with kicad-footprint-generator' keywords: 'fuse' ipc_density: 'nominal' pad_length_addition: 0 suffix: "" paste_pad: all_sides_rel: 0.9 #-10% heel_abs: -0.05 # additional heel reduction fuse_handsolder: fp_lib_name: 'Fuse' size_definitions: ['size_default_chip_devices.yaml', 'size_fuse.yaml'] ipc_reference: "ipc_spec_larger_or_equal_0603" prefix: 'Fuse' description: 'Fuse SMD {code_imperial:s} ({code_metric:s} Metric), square (rectangular) end terminal, IPC_7351 nominal with elongated pad for handsoldering. {size_info:s}, generated with kicad-footprint-generator' keywords: 'fuse handsolder' ipc_density: 'nominal' pad_length_addition: 0.35 suffix: "_Pad{pad_x:.2f}x{pad_y:.2f}mm_HandSolder" include_suffix_in_3dpath: 'False' fuse_castellated: fp_lib_name: 'Fuse' size_definitions: ['size_default_chip_devices.yaml', 'size_fuse.yaml'] ipc_reference: "ipc_spec_castellated" prefix: 'Fuse' description: 'Fuse SMD {code_imperial:s} ({code_metric:s} Metric), castellated end terminal, IPC_7351. {size_info:s}, generated with kicad-footprint-generator' keywords: 'fuse castellated' ipc_density: 'nominal' pad_length_addition: 0 suffix: "_Castellated" ================================================ FILE: scripts/SMD_chip_package_rlc-etc/SMD_chip_package_rlc-etc.py ================================================ #!/usr/bin/env python3 import sys import os import argparse import yaml import math sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA sys.path.append(os.path.join(sys.path[0], "..", "tools")) # load parent path of tools from footprint_text_fields import addTextFields from ipc_pad_size_calculators import * from drawing_tools import nearestSilkPointOnOrthogonalLineSmallClerance size_definition_path = "size_definitions/" def roundToBase(value, base): return round(value/base) * base def merge_dicts(*dict_args): """ Given any number of dicts, shallow copy and merge into a new dict, precedence goes to key value pairs in latter dicts. """ result = {} for dictionary in dict_args: result.update(dictionary) return result class TwoTerminalSMDchip(): def __init__(self, command_file, configuration): self.configuration = configuration with open(command_file, 'r') as command_stream: try: self.footprint_group_definitions = yaml.safe_load(command_stream) except yaml.YAMLError as exc: print(exc) ipc_doc = configuration['ipc_definition'] with open(ipc_doc, 'r') as ipc_stream: try: self.ipc_defintions = yaml.safe_load(ipc_stream) except yaml.YAMLError as exc: print(exc) def calcPadDetails(self, device_dimensions, ipc_data, ipc_round_base, footprint_group_data): # Zmax = Lmin + 2JT + √(CL^2 + F^2 + P^2) # Gmin = Smax − 2JH − √(CS^2 + F^2 + P^2) # Xmax = Wmin + 2JS + √(CW^2 + F^2 + P^2) # Some manufacturers do not list the terminal spacing (S) in their datasheet but list the terminal lenght (T) # Then one can calculate # Stol(RMS) = √(Ltol^2 + 2*^2) # Smin = Lmin - 2*Tmax # Smax(RMS) = Smin + Stol(RMS) manf_tol = { 'F': self.configuration.get('manufacturing_tolerance', 0.1), 'P': self.configuration.get('placement_tolerance', 0.05) } if 'terminal_width' in device_dimensions: lead_width = device_dimensions['terminal_width'] else: lead_width = device_dimensions['body_width'] Gmin, Zmax, Xmax = ipc_body_edge_inside(ipc_data, ipc_round_base, manf_tol, device_dimensions['body_length'], lead_width, lead_len=device_dimensions.get('terminal_length'), lead_inside=device_dimensions.get('terminator_spacing')) Zmax += footprint_group_data.get('pad_length_addition', 0) Pad = {'at':[-(Zmax+Gmin)/4,0], 'size':[(Zmax-Gmin)/2,Xmax]} Paste = None if 'paste_pad' in footprint_group_data: rel_reduction_factor = footprint_group_data['paste_pad'].get('all_sides_rel', 0.9) x_abs_reduction = (1 - rel_reduction_factor)*Pad['size'][0] Zmax -= 2*x_abs_reduction Gmin += 2*x_abs_reduction - 2 * footprint_group_data['paste_pad'].get('heel_abs',0) Xmax *= rel_reduction_factor Paste = {'at':[-(Zmax+Gmin)/4,0], 'size':[(Zmax-Gmin)/2,Xmax]} return Pad, Paste @staticmethod def deviceDimensions(device_size_data): dimensions = { 'body_length': TolerancedSize.fromYaml(device_size_data, base_name='body_length'), 'body_width': TolerancedSize.fromYaml(device_size_data, base_name='body_width') } if 'terminator_spacing_max' in device_size_data and 'terminator_spacing_min' in device_size_data or 'terminator_spacing' in device_size_data: dimensions['terminator_spacing'] = TolerancedSize.fromYaml(device_size_data, base_name='terminator_spacing') elif 'terminal_length_max' in device_size_data and 'terminal_length_min' in device_size_data or 'terminal_length' in device_size_data: dimensions['terminal_length'] = TolerancedSize.fromYaml(device_size_data, base_name='terminal_length') else: raise KeyError("Either terminator spacing or terminal lenght must be included in the size definition.") if 'terminal_width_min' in device_size_data and 'terminal_width_max' in device_size_data or 'terminal_width' in device_size_data: dimensions['terminal_width'] = TolerancedSize.fromYaml(device_size_data, base_name='terminal_width') return dimensions def generateFootprints(self): for group_name in self.footprint_group_definitions: #print(device_group) footprint_group_data = self.footprint_group_definitions[group_name] device_size_docs = footprint_group_data['size_definitions'] package_size_defintions={} for device_size_doc in device_size_docs: with open(size_definition_path+device_size_doc, 'r') as size_stream: try: package_size_defintions.update(yaml.safe_load(size_stream)) except yaml.YAMLError as exc: print(exc) for size_name in package_size_defintions: device_size_data = package_size_defintions[size_name] try: self.generateFootprint(device_size_data, footprint_group_data) except Exception as exc: print("Failed to generate {size_name} (group: {group_name}):".format( size_name=size_name, group_name=group_name)) print(exc) def generateFootprint(self, device_size_data, footprint_group_data): fab_line_width = self.configuration.get('fab_line_width', 0.1) silk_line_width = self.configuration.get('silk_line_width', 0.12) device_dimensions = TwoTerminalSMDchip.deviceDimensions(device_size_data) ipc_reference = footprint_group_data['ipc_reference'] ipc_density = footprint_group_data['ipc_density'] ipc_data_set = self.ipc_defintions[ipc_reference][ipc_density] ipc_round_base = self.ipc_defintions[ipc_reference]['round_base'] pad_details, paste_details = self.calcPadDetails(device_dimensions, ipc_data_set, ipc_round_base, footprint_group_data) #print(calc_pad_details()) #print("generate {name}.kicad_mod".format(name=footprint)) suffix = footprint_group_data.get('suffix', '').format(pad_x=pad_details['size'][0], pad_y=pad_details['size'][1]) prefix = footprint_group_data['prefix'] model3d_path_prefix = self.configuration.get('3d_model_prefix','${KISYS3DMOD}') suffix_3d = suffix if footprint_group_data.get('include_suffix_in_3dpath', 'True') == 'True' else "" code_metric = device_size_data.get('code_metric') code_letter = device_size_data.get('code_letter') code_imperial = device_size_data.get('code_imperial') if 'code_letter' in device_size_data: name_format = self.configuration['fp_name_tantal_format_string'] else: if 'code_metric' in device_size_data: name_format = self.configuration['fp_name_format_string'] else: name_format = self.configuration['fp_name_non_metric_format_string'] fp_name = name_format.format(prefix=prefix, code_imperial=code_imperial, code_metric=code_metric, code_letter=code_letter, suffix=suffix) fp_name_2 = name_format.format(prefix=prefix, code_imperial=code_imperial, code_letter=code_letter, code_metric=code_metric, suffix=suffix_3d) model_name = '{model3d_path_prefix:s}{lib_name:s}.3dshapes/{fp_name:s}.wrl'.format( model3d_path_prefix=model3d_path_prefix, lib_name=footprint_group_data['fp_lib_name'], fp_name=fp_name_2) #print(fp_name) #print(pad_details) kicad_mod = Footprint(fp_name) # init kicad footprint kicad_mod.setDescription(footprint_group_data['description'].format(code_imperial=code_imperial, code_metric=code_metric, code_letter=code_letter, size_info=device_size_data.get('size_info'))) kicad_mod.setTags(footprint_group_data['keywords']) kicad_mod.setAttribute('smd') pad_shape_details = {} pad_shape_details['shape'] = Pad.SHAPE_ROUNDRECT pad_shape_details['radius_ratio'] = configuration.get('round_rect_radius_ratio', 0) if 'round_rect_max_radius' in configuration: pad_shape_details['maximum_radius'] = configuration['round_rect_max_radius'] if paste_details is not None: layers_main = ['F.Cu', 'F.Mask'] kicad_mod.append(Pad(number= '', type=Pad.TYPE_SMT, layers=['F.Paste'], **merge_dicts(paste_details, pad_shape_details))) paste_details['at'][0] *= (-1) kicad_mod.append(Pad(number= '', type=Pad.TYPE_SMT, layers=['F.Paste'], **merge_dicts(paste_details, pad_shape_details))) else: layers_main = Pad.LAYERS_SMT P1 = Pad(number= 1, type=Pad.TYPE_SMT, layers=layers_main, **merge_dicts(pad_details, pad_shape_details)) pad_radius = P1.getRoundRadius() kicad_mod.append(P1) pad_details['at'][0] *= (-1) kicad_mod.append(Pad(number= 2, type=Pad.TYPE_SMT, layers=layers_main, **merge_dicts(pad_details, pad_shape_details))) fab_outline = self.configuration.get('fab_outline', 'typical') if fab_outline == 'max': outline_size = [device_dimensions['body_length'].maximum, device_dimensions['body_width'].maximum] elif fab_outline == 'min': outline_size = [device_dimensions['body_length'].minimum, device_dimensions['body_width'].minimum] else: outline_size = [device_dimensions['body_length'].nominal, device_dimensions['body_width'].nominal] if footprint_group_data.get('polarization_mark', 'False') == 'True': polararity_marker_size = self.configuration.get('fab_polarity_factor', 0.25) polararity_marker_size *= (outline_size[1] if outline_size[1] < outline_size[0] else outline_size[0]) polarity_marker_thick_line = False polarity_max_size = self.configuration.get('fab_polarity_max_size', 1) if polararity_marker_size > polarity_max_size: polararity_marker_size = polarity_max_size polarity_min_size = self.configuration.get('fab_polarity_min_size', 0.25) if polararity_marker_size < polarity_min_size: if polararity_marker_size < polarity_min_size*0.6: polarity_marker_thick_line = True polararity_marker_size = polarity_min_size silk_x_left = -abs(pad_details['at'][0]) - pad_details['size'][0]/2 - \ self.configuration['silk_pad_clearance'] - silk_line_width/2 silk_y_bottom = max( self.configuration['silk_pad_clearance'] + silk_line_width/2 + pad_details['size'][1]/2, outline_size[1]/2 + self.configuration['silk_fab_offset'] ) if polarity_marker_thick_line: kicad_mod.append(RectLine(start=[-outline_size[0]/2, outline_size[1]/2], end=[outline_size[0]/2, -outline_size[1]/2], layer='F.Fab', width=fab_line_width)) x = -outline_size[0]/2 + fab_line_width kicad_mod.append(Line(start=[x, outline_size[1]/2], end=[x, -outline_size[1]/2], layer='F.Fab', width=fab_line_width)) x += fab_line_width if x < -fab_line_width/2: kicad_mod.append(Line(start=[x, outline_size[1]/2], end=[x, -outline_size[1]/2], layer='F.Fab', width=fab_line_width)) kicad_mod.append(Circle(center=[silk_x_left-0.05, 0], radius=0.05, layer="F.SilkS", width=0.1)) else: poly_fab= [ {'x':outline_size[0]/2,'y':-outline_size[1]/2}, {'x':polararity_marker_size - outline_size[0]/2,'y':-outline_size[1]/2}, {'x':-outline_size[0]/2,'y':polararity_marker_size-outline_size[1]/2}, {'x':-outline_size[0]/2,'y':outline_size[1]/2}, {'x':outline_size[0]/2,'y':outline_size[1]/2}, {'x':outline_size[0]/2,'y':-outline_size[1]/2} ] kicad_mod.append(PolygoneLine(polygone=poly_fab, layer='F.Fab', width=fab_line_width)) poly_silk = [ {'x':outline_size[0]/2,'y':-silk_y_bottom}, {'x':silk_x_left,'y':-silk_y_bottom}, {'x':silk_x_left,'y':silk_y_bottom}, {'x':outline_size[0]/2,'y':silk_y_bottom} ] kicad_mod.append(PolygoneLine(polygone=poly_silk, layer='F.SilkS', width=silk_line_width)) else: kicad_mod.append(RectLine(start=[-outline_size[0]/2, outline_size[1]/2], end=[outline_size[0]/2, -outline_size[1]/2], layer='F.Fab', width=fab_line_width)) silk_outline_y = outline_size[1]/2 + self.configuration['silk_fab_offset'] default_clearance = self.configuration.get('silk_pad_clearance', 0.2) silk_point_top_right = nearestSilkPointOnOrthogonalLineSmallClerance( pad_size=pad_details['size'], pad_position=pad_details['at'], pad_radius=pad_radius, fixed_point=Vector2D(0, silk_outline_y), moving_point=Vector2D(outline_size[0]/2, silk_outline_y), silk_pad_offset_default=(silk_line_width/2+default_clearance), silk_pad_offset_reduced=(silk_line_width/2\ +self.configuration.get('silk_clearance_small_parts', default_clearance)), min_lenght=configuration.get('silk_line_lenght_min', 0)/2) if silk_point_top_right: kicad_mod.append(Line( start=[-silk_point_top_right.x, -silk_point_top_right.y], end=[silk_point_top_right.x, -silk_point_top_right.y], layer='F.SilkS', width=silk_line_width)) kicad_mod.append(Line( start=[-silk_point_top_right.x, silk_point_top_right.y], end=silk_point_top_right, layer='F.SilkS', width=silk_line_width)) CrtYd_rect = [None,None] CrtYd_rect[0] = roundToBase(2 * abs(pad_details['at'][0]) + \ pad_details['size'][0] + 2 * ipc_data_set['courtyard'], 0.02) if pad_details['size'][1] > outline_size[1]: CrtYd_rect[1] = pad_details['size'][1] + 2 * ipc_data_set['courtyard'] else: CrtYd_rect[1] = outline_size[1] + 2 * ipc_data_set['courtyard'] CrtYd_rect[1] = roundToBase(CrtYd_rect[1], 0.02) kicad_mod.append(RectLine(start=[-CrtYd_rect[0]/2, CrtYd_rect[1]/2], end=[CrtYd_rect[0]/2, -CrtYd_rect[1]/2], layer='F.CrtYd', width=self.configuration['courtyard_line_width'])) ######################### Text Fields ############################### addTextFields(kicad_mod=kicad_mod, configuration=configuration, body_edges={'left':-outline_size[0]/2,'right':outline_size[0]/2, 'top':-outline_size[1]/2,'bottom':outline_size[1]/2}, courtyard={'top':-CrtYd_rect[1]/2, 'bottom':CrtYd_rect[1]/2}, fp_name=fp_name, text_y_inside_position='center') kicad_mod.append(Model(filename=model_name)) output_dir = '{lib_name:s}.pretty/'.format(lib_name=footprint_group_data['fp_lib_name']) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) filename = '{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=fp_name) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description='use confing .yaml files to create footprints.') parser.add_argument('files', metavar='file', type=str, nargs='+', help='list of files holding information about what devices should be created.') parser.add_argument('--global_config', type=str, nargs='?', help='the config file defining how the footprint will look like. (KLC)', default='../tools/global_config_files/config_KLCv3.0.yaml') parser.add_argument('--series_config', type=str, nargs='?', help='the config file defining series parameters.', default='config_KLCv3.0.yaml') parser.add_argument('--ipc_definition', type=str, nargs='?', help='the ipc definition file', default='ipc7351B_smd_two_terminal_chip.yaml') parser.add_argument('--force_rectangle_pads', action='store_true', help='Force the generation of rectangle pads instead of rounded rectangle (KiCad 4.x compatibility.)') args = parser.parse_args() with open(args.global_config, 'r') as config_stream: try: configuration = yaml.safe_load(config_stream) except yaml.YAMLError as exc: print(exc) with open(args.series_config, 'r') as config_stream: try: configuration.update(yaml.safe_load(config_stream)) except yaml.YAMLError as exc: print(exc) args = parser.parse_args() configuration['ipc_definition'] = args.ipc_definition if args.force_rectangle_pads: configuration['round_rect_max_radius'] = None configuration['round_rect_radius_ratio'] = 0 for filepath in args.files: two_terminal_smd =TwoTerminalSMDchip(filepath, configuration) two_terminal_smd.generateFootprints() ================================================ FILE: scripts/SMD_chip_package_rlc-etc/config_KLCv3.0.yaml ================================================ # This holds the configuration information # using this config file will create KLCv3.0 compatible footprints. placement_tolerance: 0.05 manufacturing_tolerance: 0.1 fp_name_format_string: '{prefix:s}_{code_imperial:s}_{code_metric:s}Metric{suffix:s}' fp_name_non_metric_format_string: '{prefix:s}_{code_imperial:s}{suffix:s}' fp_name_tantal_format_string: '{prefix:s}_EIA-{code_metric:s}_{code_letter:s}{suffix:s}' 3d_model_prefix: '${KISYS3DMOD}/' fab_outline: 'typical' # typical | max | min fab_polarity_min_size: 0.3 fab_polarity_max_size: 1 fab_polarity_factor: 0.25 silk_clearance_small_parts: 0.1 ================================================ FILE: scripts/SMD_chip_package_rlc-etc/ipc7351B_smd_two_terminal_chip.yaml ================================================ # Dimensions taken from ipc7351b # < 0603 (1608 Metric) # | Minimum | Median | Maximum | # | (Least) | (Nominal) | (Most) | # | Density | Density | Density | round # Lead Part | Level C | Level B | Level A | to # ----------+---------+-----------+---------+- # Toe (JT) | 0.1 | 0.2 | 0.3 | 0.02 # Heel (JH) | 0.0 | 0.0 | 0.0 | 0.02 # Side (JS) | -0.05 | 0.0 | 0.05 | 0.02 # Courtyard | 0.1 | 0.15 | 0.2 | ipc_spec_smaller_0603: least: toe: 0.1 heel: 0 side: -0.05 courtyard: 0.1 nominal: toe: 0.2 heel: 0 side: 0.0 courtyard: 0.15 most: toe: 0.3 heel: 0 side: 0.05 courtyard: 0.2 round_base: toe: 0.02 heel: 0.02 side: 0.02 # >= 0603 (1608 Metric) # | Minimum | Median | Maximum # | (Least) | (Nominal) | (Most) # | Density | Density | Density # Lead Part | Level C | Level B | Level A # ----------+---------+-----------+-------- # Toe (JT) | 0.15 | 0.35 | 0.55 # Heel (JH) | 0.0 | 0.0 | 0.0 # Side (JS) | -0.05 | 0.00 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 ipc_spec_larger_or_equal_0603: least: toe: 0.15 heel: 0.0 side: -0.05 courtyard: 0.1 nominal: toe: 0.35 heel: 0.0 side: 0.00 courtyard: 0.25 most: toe: 0.55 heel: 0.0 side: 0.05 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 # tantalum cap # | Minimum | Median | Maximum # | (Least) | (Nominal) | (Most) # | Density | Density | Density # Lead Part | Level C | Level B | Level A # ----------+---------+-----------+-------- # Toe (JT) | 0.07 | 0.15 | 0.25 # Heel (JH) | 0.20 | 0.50 | 0.80 # Side (JS) | -0.10 | -0.05 | 0.01 # Courtyard | 0.1 | 0.25 | 0.5 ipc_spec_tantalumn: least: toe: 0.07 heel: 0.2 side: -0.1 courtyard: 0.1 nominal: toe: 0.15 heel: 0.5 side: -0.05 courtyard: 0.25 most: toe: 0.25 heel: 0.8 side: 0.01 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 # castellated # The document is a bit strange with the castellated definitions. # They seem to exchange the toe and heel fillet. # For square terminated parts the toe fillet is towards the outside = Z measurement # But for castellated they tell us that the heel fillet is responsible for the Z measurement. # As the script interprets toe to point outwards (=Z dim) we change these two compared to the # ipc document. # | Minimum | Median | Maximum # | (Least) | (Nominal) | (Most) # | Density | Density | Density # Lead Part | Level C | Level B | Level A # ----------+---------+-----------+-------- # Toe (JT) | 0.45 | 0.55 | 0.65 # Heel (JH) | 0.05 | 0.15 | 0.25 # Side (JS) | -0.15 | -0.05 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 ipc_spec_castellated: least: toe: 0.45 heel: 0.05 side: -0.15 courtyard: 0.1 nominal: toe: 0.55 heel: 0.15 side: -0.05 courtyard: 0.25 most: toe: 0.65 heel: 0.25 side: 0.05 courtyard: 0.5 round_base: toe: 0.05 heel: 0.05 side: 0.05 ================================================ FILE: scripts/SMD_chip_package_rlc-etc/ipc_smd_two_terminal_chip.yaml ================================================ # IPC IPC-7351 http://pcbget.ru/Files/Standarts/IPC_7351.pdf # Page 23 # < 0603 (1608 Metric) # | Minimum | Median | Maximum | # | (Least) | (Nominal) | (Most) | # | Density | Density | Density | round # Lead Part | Level C | Level B | Level A | to # ----------+---------+-----------+---------+- # Toe (JT) | 0.0 | 0.1 | 0.2 | 0.05 # Heel (JH) | -0.05 | -0.05 | -0.05 | 0.05 # Side (JS) | 0.00 | 0.00 | 0.05 | 0.05 # Courtyard | 0.1 | 0.15 | 0.2 | ipc_spec_smaller_0603: least: toe: 0.0 heel: -0.05 side: 0.0 courtyard: 0.1 nominal: toe: 0.1 heel: -0.05 side: 0.0 courtyard: 0.15 most: toe: 0.2 heel: -0.05 side: 0.05 courtyard: 0.2 round_base: toe: 0.05 heel: 0.05 side: 0.05 # >= 0603 (1608 Metric) # | Minimum | Median | Maximum # | (Least) | (Nominal) | (Most) # | Density | Density | Density # Lead Part | Level C | Level B | Level A # ----------+---------+-----------+-------- # Toe (JT) | 0.15 | 0.35 | 0.55 # Heel (JH) | -0.05 | -0.05 | -0.05 # Side (JS) | -0.05 | 0.00 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 ipc_spec_larger_or_equal_0603: least: toe: 0.15 heel: -0.05 side: -0.05 courtyard: 0.1 nominal: toe: 0.35 heel: -0.05 side: 0.00 courtyard: 0.25 most: toe: 0.55 heel: -0.05 side: 0.05 courtyard: 0.5 round_base: toe: 0.02 heel: 0.02 side: 0.1 # tantalum cap # | Minimum | Median | Maximum # | (Least) | (Nominal) | (Most) # | Density | Density | Density # Lead Part | Level C | Level B | Level A # ----------+---------+-----------+-------- # Toe (JT) | 0.07 | 0.15 | 0.25 # Heel (JH) | 0.20 | 0.50 | 0.80 # Side (JS) | -0.10 | -0.05 | 0.01 # Courtyard | 0.1 | 0.25 | 0.5 ipc_spec_tantalumn: least: toe: 0.07 heel: 0.2 side: -0.1 courtyard: 0.1 nominal: toe: 0.15 heel: 0.5 side: -0.05 courtyard: 0.25 most: toe: 0.25 heel: 0.8 side: 0.01 courtyard: 0.5 round_base: toe: 0.02 heel: 0.02 side: 0.1 # castellated # The document is a bit strange with the castellated definitions. # They seem to exchange the toe and heel fillet. # For square terminated parts the toe fillet is towards the outside = Z measurement # But for castellated they tell us that the heel fillet is responsible for the Z measurement. # As the script interprets toe to point outwards (=Z dim) we change these two compared to the # ipc document. # | Minimum | Median | Maximum # | (Least) | (Nominal) | (Most) # | Density | Density | Density # Lead Part | Level C | Level B | Level A # ----------+---------+-----------+-------- # Toe (JT) | 0.45 | 0.55 | 0.65 # Heel (JH) | 0.05 | 0.15 | 0.25 # Side (JS) | -0.15 | -0.05 | 0.05 # Courtyard | 0.1 | 0.25 | 0.5 ipc_spec_castellated: least: toe: 0.45 heel: 0.05 side: -0.15 courtyard: 0.1 nominal: toe: 0.55 heel: 0.15 side: -0.05 courtyard: 0.25 most: toe: 0.65 heel: 0.25 side: 0.05 courtyard: 0.5 round_base: toe: 0.02 heel: 0.02 side: 0.01 ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_capacitor_chip_devices.yaml ================================================ SMD_1825: code_imperial: "1825" code_metric: "4564" body_length: nominal: 4.6 tolerance: 0.5 body_width: nominal: 6.3 tolerance: 0.4 terminal_length: nominal: 0.75 tolerance: 0.35 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size from: http://datasheets.avx.com/AVX-HV_MLCC.pdf)' SMD_2220: code_imperial: "2220" code_metric: "5650" body_length: nominal: 5.7 tolerance: 0.5 body_width: nominal: 5.0 tolerance: 0.4 terminal_length: nominal: 0.85 tolerance: 0.35 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size from: http://datasheets.avx.com/AVX-HV_MLCC.pdf)' SMD_2225: code_imperial: "2225" code_metric: "5664" body_length: nominal: 5.72 tolerance: 0.25 body_width: nominal: 6.35 tolerance: 0.25 terminal_length: nominal: 0.85 tolerance: 0.35 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size from: http://datasheets.avx.com/AVX-HV_MLCC.pdf)' SMD_3640: code_imperial: "3640" code_metric: "9110" body_length: nominal: 9.14 tolerance: 0.25 body_width: nominal: 10.2 tolerance: 0.25 terminal_length: minimum: 0.76 maximum: 1.52 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size from: http://datasheets.avx.com/AVX-HV_MLCC.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_default_chip_devices.yaml ================================================ SMD_0603: code_imperial: "0603" code_metric: "1608" body_length: 1.6 body_length_min: 1.5 body_length_max: 1.7 body_width: 0.8 body_width_min: 0.7 body_width_max: 0.95 terminator_spacing_min: 0.7 terminator_spacing_max: 1.11 size_info: '(Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf)' SMD_0805: code_imperial: "0805" code_metric: "2012" body_length: 2.0 body_length_min: 1.86 body_length_max: 2.15 body_width: 1.2 body_width_min: 1.12 body_width_max: 1.38 terminator_spacing_min: 0.89 terminator_spacing_max: 1.55 size_info: '(Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing)' # SMD_1008: # I did not find any part that uses this package. # code_imperial: "1008" # code_metric: "2520" # body_length: 2.5 # body_length_min: # body_width: 2.0 # body_width_min: # terminator_spacing_max: SMD_1206: code_imperial: "1206" code_metric: "3216" body_length: 3.2 body_length_min: 3.05 body_length_max: 3.35 body_width: 1.6 body_width_min: 1.45 body_width_max: 1.75 terminator_spacing_min: 1.55 terminator_spacing_max: 2.32 size_info: '(Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf)' SMD_1210: code_imperial: "1210" code_metric: "3225" body_length: 3.2 body_length_min: 3.05 body_length_max: 3.35 body_width: 2.5 body_width_min: 2.34 body_width_max: 2.64 terminator_spacing_min: 1.55 terminator_spacing_max: 2.32 size_info: '(Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf)' SMD_1806: code_imperial: "1806" code_metric: "4516" body_length: nominal: 4.5 tolerance: 0.2 body_width: nominal: 1.6 tolerance: 0.2 terminal_length: nominal: 0.7 tolerance: 0.3 size_info: '(Body size source: https://www.modelithics.com/models/Vendor/MuRata/BLM41P.pdf)' SMD_1812: code_imperial: "1812" code_metric: "4532" body_length: nominal: 4.5 tolerance: 0.2 body_width: nominal: 3.2 tolerance: 0.2 terminal_length: nominal: 0.5 tolerance: 0.2 size_info: '(Body size source: https://www.nikhef.nl/pub/departments/mt/projects/detectorR_D/dtddice/ERJ2G.pdf)' SMD_2010: code_imperial: "2010" code_metric: "5025" body_length: 5.0 body_length_min: 4.85 body_length_max: 5.15 body_width: 2.5 body_width_min: 2.35 body_width_max: 2.65 terminator_spacing_min: 3.15 terminator_spacing_max: 3.92 size_info: '(Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf)' SMD_2512: code_imperial: "2512" code_metric: "6332" body_length: 6.3 body_length_min: 6.15 body_length_max: 6.45 body_width: 3.2 body_width_min: 3.05 body_width_max: 3.35 terminator_spacing_min: 4.45 terminator_spacing_max: 5.22 size_info: '(Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf)' SMD_2816: code_imperial: "2816" code_metric: "7142" body_length: nominal: 7.1 tolerance: 0.254 body_width: nominal: 4.2 tolerance: 0.254 terminal_length_min: 1.316 terminal_length_max: 2.744 size_info: '(Body size from: https://www.vishay.com/docs/30100/wsl.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_default_chip_devices_smaller_0402.yaml ================================================ SMD_01005: code_imperial: "01005" code_metric: "0402" body_length: nominal: 0.4 tolerance: 0.02 body_width: nominal: 0.2 tolerance: 0.02 terminal_length: nominal: 0.1 tolerance: 0.03 size_info: '(Body size source: http://www.vishay.com/docs/20056/crcw01005e3.pdf)' SMD_0201: code_imperial: "0201" code_metric: "0603" body_length: nominal: 0.6 tolerance: 0.05 body_width: nominal: 0.3 tolerance: 0.05 terminal_length: nominal: 0.15 tolerance: 0.05 size_info: '(Body size source: https://www.vishay.com/docs/20052/crcw0201e3.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_default_chip_devices_smaller_0603.yaml ================================================ SMD_0402: code_imperial: "0402" code_metric: "1005" body_length: nominal: 1.0 minimum: 1.0 maximum: 1.1 body_width: nominal: 0.5 minimum: 0.48 maximum: 0.6 terminator_spacing_min: 0.4 terminator_spacing_max: 0.7 size_info: '(Body size source: http://www.tortai-tech.com/upload/download/2011102023233369053.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_diode.yaml ================================================ SMD_2114: code_imperial: "2114" code_metric: "3652" body_length: nominal: 5.2 tolerance: 0.1 body_width: nominal: 3.6 tolerance: 0.1 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.15 tolerance: 0.1 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size from: http://datasheets.avx.com/schottky.pdf)' SMD_3220: code_imperial: "3220" code_metric: "8050" body_length: nominal: 8.0 tolerance: 0.1 body_width: nominal: 5.0 tolerance: 0.1 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.95 tolerance: 0.1 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size from: http://datasheets.avx.com/schottky.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_fuse.yaml ================================================ SMD_2920: code_imperial: "2920" code_metric: "7451" body_length_min: 6.73 body_length_max: 7.98 body_width_min: 4.8 body_width_max: 5.44 terminal_length_min: 0.5 terminal_length_max: 1.2 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size from: http://www.megastar.com/products/fusetronic/polyswitch/PDF/smd2920.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_inductor.yaml ================================================ SMD_1008: code_imperial: "1008" code_metric: "2520" body_length: nominal: 2.5 tolerance: 0.2 body_width: nominal: 2.0 tolerance: 0.2 terminal_length: nominal: 0.6 tolerance: 0.25 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size source: https://ecsxtal.com/store/pdf/ECS-MPI2520-SMD-POWER-INDUCTOR.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_resistor.yaml ================================================ SMD_4020: code_imperial: "4020" code_metric: "10251" body_length: nominal: 10.2 tolerance: [0.05, 0.2] body_width: nominal: 5.1 tolerance: [0.05, 0.2] terminal_length: nominal: 0.9 tolerance: 0.2 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size source: http://datasheet.octopart.com/HVC0603T5004FET-Ohmite-datasheet-26699797.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_tantal.yaml ================================================ SMD_1608-08: code_metric: '1608-08' # size | 1,6 x 0,8 x 0,8 mm #code_letter: 'Kemet-—' code_letter: 'AVX-J' body_length: 1.6 body_length_tol: 0.2 body_width: 0.85 body_width_tol: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: 0.5 terminal_length_tol: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: https://www.vishay.com/docs/48064/_t58_vmn_pt0471_1601.pdf)' SMD_1608-10: code_metric: '1608-10' # size | 1,6 x 0,85 x 1,05 mm #code_letter: 'Kemet-—' code_letter: 'AVX-L' body_length: 1.6 body_length_tol: 0.2 body_width: 0.85 body_width_tol: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: 0.5 terminal_length_tol: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: https://www.vishay.com/docs/48064/_t58_vmn_pt0471_1601.pdf)' SMD_2012-12: code_metric: '2012-12' # size | 2,05 x 1,35 x 1,2 mm code_letter: 'Kemet-R' #code_letter: 'AVX-R' body_length: nominal: 2.0 tolerance: 0.2 body_width: nominal: 1.25 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.5 tolerance: 0.2 terminal_width: nominal: 0.9 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: https://www.vishay.com/docs/40182/tmch.pdf)' SMD_2012-15: code_metric: '2012-15' # size | 2,05 x 1,35 x 1,5 mm #code_letter: 'Kemet-—' code_letter: 'AVX-P' body_length: nominal: 2.0 tolerance: 0.2 body_width: nominal: 1.25 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.5 tolerance: 0.2 terminal_width: nominal: 0.9 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: https://www.vishay.com/docs/40182/tmch.pdf)' SMD_3216-10: code_metric: '3216-10' # size | 3,2 x 1,6 x 1,0 mm code_letter: 'Kemet-I' #code_letter: 'AVX-K' body_length: nominal: 3.2 tolerance: 0.2 body_width: nominal: 1.6 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.8 tolerance: [0.3, 0.2] terminal_width: nominal: 1.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_3216-12: code_metric: '3216-12' # size | 3,2 x 1,6 x 1,2 mm code_letter: 'Kemet-S' #code_letter: 'AVX-S' body_length: nominal: 3.2 tolerance: 0.2 body_width: nominal: 1.6 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.8 tolerance: [0.3, 0.2] terminal_width: nominal: 1.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_3216-18: code_metric: '3216-18' # size | 3,2 x 1,6 x 1,8 mm code_letter: 'Kemet-A' #code_letter: 'AVX-A' body_length: nominal: 3.2 tolerance: 0.2 body_width: nominal: 1.6 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.8 tolerance: [0.3, 0.2] terminal_width: nominal: 1.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_3528-12: code_metric: '3528-12' # size | 3,5 x 2,8 x 1,2 mm code_letter: 'Kemet-T' #code_letter: 'AVX-T' body_length: nominal: 3.5 tolerance: 0.2 body_width: nominal: 2.8 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.8 tolerance: [0.3, 0.1] terminal_width: nominal: 2.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_3528-15: code_metric: '3528-15' # size | 3,5 x 2,8 x 1,5 mm #code_letter: 'Kemet-—' code_letter: 'AVX-H' body_length: nominal: 3.5 tolerance: 0.2 body_width: nominal: 2.8 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.8 tolerance: [0.3, 0.1] terminal_width: nominal: 2.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_3528-21: code_metric: '3528-21' # size | 3,5 x 2,8 x 2,1 mm code_letter: 'Kemet-B' #code_letter: 'AVX-B' body_length: nominal: 3.5 tolerance: 0.2 body_width: nominal: 2.8 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 0.8 tolerance: [0.3, 0.1] terminal_width: nominal: 2.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_6032-15: code_metric: '6032-15' # size | 6,0 x 3,2 x 1,5 mm code_letter: 'Kemet-U' #code_letter: 'AVX-W' body_length: nominal: 6.0 tolerance: 0.3 body_width: nominal: 3.2 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_6032-20: code_metric: '6032-20' # size | 6,0 x 3,2 x 2,0 mm #code_letter: 'Kemet-—' code_letter: 'AVX-F' body_length: nominal: 6.0 tolerance: 0.3 body_width: nominal: 3.2 tolerance: 0.2 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_6032-28: code_metric: '6032-28' # size | 6,0 x 3,2 x 2,8 mm code_letter: 'Kemet-C' #code_letter: 'AVX-C' body_length: nominal: 6.0 tolerance: 0.3 body_width: nominal: 3.2 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.2 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7132-20: code_metric: '7132-20' # size | 7,1 x 3,2 x 2,0 mm code_letter: 'AVX-U' body_length: nominal: 7.1 tolerance: 0.3 body_width: nominal: 3.2 tolerance: 0.3 terminal_length: nominal: 1.3 tolerance: 0.3 terminator_spacing: nominal: 3.6 tolerance: 0.6 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/F72-F75.pdf)' SMD_7132-28: code_metric: '7132-28' # size | 7,1 x 3,2 x 2,8 mm code_letter: 'AVX-C' body_length: nominal: 7.1 tolerance: 0.3 body_width: nominal: 3.2 tolerance: 0.3 terminal_length: nominal: 1.3 tolerance: 0.3 terminator_spacing: nominal: 3.6 tolerance: 0.6 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/F72-F75.pdf)' SMD_7260-15: code_metric: '7260-15' # size | 7,2 x 6,0 x 1,5 mm code_letter: 'AVX-R' body_length: nominal: 7.2 tolerance: 0.3 body_width: nominal: 6.0 tolerance: 0.3 terminator_spacing: nominal: 3.8 tolerance: 0.6 terminal_length: nominal: 1.3 tolerance: 0.4 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/F72-F75.pdf)' SMD_7260-20: code_metric: '7260-20' # size | 7,2 x 6,0 x 2,0 mm code_letter: 'AVX-M' body_length: nominal: 7.2 tolerance: 0.3 body_width: nominal: 6.0 tolerance: 0.3 terminator_spacing: nominal: 3.8 tolerance: 0.6 terminal_length: nominal: 1.3 tolerance: 0.4 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/F72-F75.pdf)' SMD_7260-28: code_metric: '7260-28' # size | 7,2 x 6,0 x 2,8 mm code_letter: 'AVX-M' body_length: nominal: 7.2 tolerance: 0.3 body_width: nominal: 6.0 tolerance: 0.3 terminator_spacing: nominal: 3.8 tolerance: 0.6 terminal_length: nominal: 1.3 tolerance: 0.4 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/F72-F75.pdf)' SMD_7260-38: code_metric: '7260-38' # size | 7,2 x 6,0 x 3,8 mm code_letter: 'AVX-R' body_length: nominal: 7.2 tolerance: 0.3 body_width: nominal: 6.0 tolerance: 0.3 terminator_spacing: nominal: 3.8 tolerance: 0.6 terminal_length: nominal: 1.3 tolerance: 0.4 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/F72-F75.pdf)' SMD_7343-15: code_metric: '7343-15' # size | 7,3 x 4,3 x 1,5 mm code_letter: 'Kemet-W' #code_letter: 'AVX-X' body_length: nominal: 7.3 tolerance: 0.3 body_width: nominal: 4.3 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width_min: 2.3 terminal_width_max: 2.5 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7343-20: code_metric: '7343-20' # size | 7,3 x 4,3 x 2,0 mm code_letter: 'Kemet-V' #code_letter: 'AVX-Y' body_length: nominal: 7.3 tolerance: 0.3 body_width: nominal: 4.3 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.4 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7343-30: code_metric: '7343-30' # size | 7,3 x 4,3 x 3,0 mm #code_letter: 'Kemet-—' code_letter: 'AVX-N' body_length: nominal: 7.3 tolerance: 0.3 body_width: nominal: 4.3 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.4 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7343-31: code_metric: '7343-31' # size | 7,3 x 4,3 x 3,1 mm code_letter: 'Kemet-D' #code_letter: 'AVX-D' body_length: nominal: 7.3 tolerance: 0.3 body_width: nominal: 4.3 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.4 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7343-40: code_metric: '7343-40' # size | 7,3 x 4,3 x 4,0 mm code_letter: 'Kemet-Y' #code_letter: 'AVX-—' body_length: nominal: 7.3 tolerance: 0.3 body_width: nominal: 4.3 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.4 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7343-43: code_metric: '7343-43' # size | 7,3 x 4,3 x 4,3 mm code_letter: 'Kemet-X' #code_letter: 'AVX-E' body_length: nominal: 7.3 tolerance: 0.3 body_width: nominal: 4.3 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 2.4 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7360-38: code_metric: '7360-38' # size | 7,3 x 6,0 x 3,8 mm code_letter: 'Kemet-E' #code_letter: 'AVX-—' body_length: nominal: 7.3 tolerance: 0.3 body_width: nominal: 6.0 tolerance: 0.3 #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: 0.3 terminal_width: nominal: 4.1 tolerance: 0.1 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://www.kemet.com/Lists/ProductCatalog/Attachments/253/KEM_TC101_STD.pdf)' SMD_7361-38: code_metric: '7361-38' # size | 7,3 x 6,1 x 3,8 mm #code_letter: 'Kemet-—' code_letter: 'AVX-V' body_length: nominal: 7.3 tolerance: 0.2 body_width: nominal: 6.1 tolerance: [0.1, 0.2] #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: [0.2, 0.3] terminal_width: nominal: 3.1 tolerance: 0.2 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/NOS.pdf)' SMD_7361-438: code_metric: '7361-438' # size | 7,3 x 6,1 x 4,3 mm #code_letter: 'Kemet-—' code_letter: 'AVX-U' body_length: nominal: 7.3 tolerance: 0.2 body_width: nominal: 6.1 tolerance: [0.1, 0.2] #terminator_spacing_min: #terminator_spacing_max: terminal_length: nominal: 1.3 tolerance: [0.2, 0.3] terminal_width: nominal: 3.1 tolerance: 0.2 ipc_reference: "ipc_spec_tantalumn" size_info: '(Body size from: http://datasheets.avx.com/NOS.pdf)' ================================================ FILE: scripts/SMD_chip_package_rlc-etc/size_definitions/size_wide_body_chip_resistor.yaml ================================================ SMD_0612: code_imperial: "0612" code_metric: "1632" body_length: nominal: 1.6 tolerance: 0.2 body_width: nominal: 3.2 tolerance: 0.2 terminal_length: nominal: 0.4 tolerance: 0.15 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size source: https://www.vishay.com/docs/20019/rcwe.pdf)' SMD_0815: code_imperial: "0815" code_metric: "2038" body_length: nominal: 2.15 tolerance: 0.2 body_width: nominal: 3.75 tolerance: 0.25 terminal_length: nominal: 0.7 tolerance: 0.25 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size source: http://www.yageo.com/documents/recent/PYu-PRPFPH_521_RoHS_L_0.pdf)' SMD_1020: code_imperial: "1020" code_metric: "2550" body_length: nominal: 2.5 tolerance: 0.2 body_width: nominal: 5.0 tolerance: 0.2 terminal_length: nominal: 0.55 tolerance: 0.15 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size source: https://www.vishay.com/docs/20019/rcwe.pdf)' SMD_1218: code_imperial: "1218" code_metric: "3246" body_length: nominal: 3.2 tolerance: [0.2, 0.1] body_width: nominal: 4.6 tolerance: 0.15 terminal_length: nominal: 0.45 tolerance: 0.2 ipc_reference: "ipc_spec_larger_or_equal_0603" size_info: '(Body size source: https://www.vishay.com/docs/20035/dcrcwe3.pdf)' ================================================ FILE: scripts/Shielding/laird_technologies_smd_shielding.kicad_mod.yaml ================================================ # page 9 Laird_Technologies_BMI-S-101_13.66x12.70mm: description: "Laird Technologies BMI-S-101 Shielding Cabinet One Piece SMD 13.66x12.70mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 12.70 y_part_size: 13.66 x_pad_spacer: [1.9, 4.1, 6.75] y_pad_spacer: [1.9, 4.1, 7.23] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-201-F_13.66x12.70mm: description: "Laird Technologies BMI-S-201-F Shielding Cabinet Two Piece SMD 13.66x12.70mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 12.70 y_part_size: 13.66 x_pad_spacer: [1.9, 4.1, 6.75] y_pad_spacer: [1.9, 4.1, 7.23] x_pad_mirror: True y_pad_mirror: True # page 10 Laird_Technologies_BMI-S-102_16.50x16.50mm: description: "Laird Technologies BMI-S-102 Shielding Cabinet One Piece SMD 16.50x16.50mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 16.50 y_part_size: 16.50 x_pad_spacer: [1.9, 4.1, 8.65] y_pad_spacer: [1.9, 4.1, 8.65] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-202-F_16.50x16.50mm: description: "Laird Technologies BMI-S-202-F Shielding Cabinet Two Piece SMD 16.50x16.50mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 16.50 y_part_size: 16.50 x_pad_spacer: [1.9, 4.1, 8.65] y_pad_spacer: [1.9, 4.1, 8.65] x_pad_mirror: True y_pad_mirror: True # page 11 Laird_Technologies_BMI-S-103_26.21x26.21mm: description: "Laird Technologies BMI-S-103 Shielding Cabinet One Piece SMD 26.21x26.21mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 26.21 y_part_size: 26.21 x_pad_spacer: [1.735, 3.935, 7.735, 9.935, 13.505] y_pad_spacer: [1.735, 3.935, 7.735, 9.935, 13.505] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-203-F_26.21x26.21mm: description: "Laird Technologies BMI-S-203-F Shielding Cabinet Two Piece SMD 26.21x26.21mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 26.21 y_part_size: 26.21 x_pad_spacer: [1.735, 3.935, 7.735, 9.935, 13.505] y_pad_spacer: [1.735, 3.935, 7.735, 9.935, 13.505] x_pad_mirror: True y_pad_mirror: True # page 12 Laird_Technologies_BMI-S-104_32.00x32.00mm: description: "Laird Technologies BMI-S-104 Shielding Cabinet One Piece SMD 32.00x32.00mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 32.00 y_part_size: 32.00 x_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 16.4] y_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 16.4] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-204-F_32.00x32.00mm: description: "Laird Technologies BMI-S-204-F Shielding Cabinet Two Piece SMD 32.00x32.00mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 32.00 y_part_size: 32.00 x_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 16.4] y_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 16.4] x_pad_mirror: True y_pad_mirror: True # page 13 Laird_Technologies_BMI-S-105_38.10x25.40mm: description: "Laird Technologies BMI-S-105 Shielding Cabinet One Piece SMD 38.10x25.40mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 38.10 y_part_size: 25.40 x_pad_spacer: [1.65, 4.35, 7.65, 10.35, 13.65, 16.35, 19.45] # used: 3.3 - 2.7 - 3.3 - ... y_pad_spacer: [1.65, 4.35, 7.65, 10.35, 13.1] # used: 3.3 - 2.7 -3.3 x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-205-F_38.10x25.40mm: description: "Laird Technologies BMI-S-205-F Shielding Cabinet Two Piece SMD 38.10x25.40mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 38.10 y_part_size: 25.40 x_pad_spacer: [1.65, 4.35, 7.65, 10.35, 13.65, 16.35, 19.45] # used: 3.3 - 2.7 - 3.3 - ... y_pad_spacer: [1.65, 4.35, 7.65, 10.35, 13.1] # used: 3.3 - 2.7 -3.3 x_pad_mirror: True y_pad_mirror: True # page 14 Laird_Technologies_BMI-S-106_36.83x33.68mm: description: "Laird Technologies BMI-S-106 Shielding Cabinet One Piece SMD 36.83x33.68mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 36.83 y_part_size: 33.68 x_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 18.82] # footprint is 0.1mm wider than on datasheet y_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 17.24] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-206-F_36.83x33.68mm: description: "Laird Technologies BMI-S-206-F Shielding Cabinet Two Piece SMD 36.83x33.68mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 36.83 y_part_size: 33.68 x_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 18.82] # footprint is 0.1mm wider than on datasheet y_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 17.24] x_pad_mirror: True y_pad_mirror: True # page 15 Laird_Technologies_BMI-S-107_44.37x44.37mm: description: "Laird Technologies BMI-S-107 Shielding Cabinet One Piece SMD 44.37x44.37mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 44.37 y_part_size: 44.37 # 2.3 3.8 2.2 3.8 2.2 3.8 2.2 x_pad_spacer: [1.15, 4.95, 7.15, 10.95, 13.15, 16.95, 19.15, 22.59] # footprint is 0.1mm wider than on datasheet and centered y_pad_spacer: [1.15, 4.95, 7.15, 10.95, 13.15, 16.95, 19.15, 22.59] # footprint is 0.1mm wider than on datasheet and centered x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-207-F_44.37x44.37mm: description: "Laird Technologies BMI-S-207-F Shielding Cabinet Two Piece SMD 44.37x44.37mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 44.37 y_part_size: 44.37 x_pad_spacer: [1.15, 4.95, 7.15, 10.95, 13.15, 16.95, 19.15, 22.59] # footprint is 0.1mm wider than on datasheet and centered y_pad_spacer: [1.15, 4.95, 7.15, 10.95, 13.15, 16.95, 19.15, 22.59] # footprint is 0.1mm wider than on datasheet and centered x_pad_mirror: True y_pad_mirror: True # page 16 Laird_Technologies_BMI-S-208-F_39.60x39.60mm: description: "Laird Technologies BMI-S-208-F Shielding Cabinet Two Piece SMD 39.60x39.60mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 39.6 y_part_size: 39.6 x_pad_spacer: [1.9, 4.1, 7.9, 10.1, 13.9, 16.1, 20.2] y_pad_spacer: [1.9, 4.1, 7.9, 10.1, 13.9, 16.1, 20.2] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-209-F_29.36x18.50mm: description: "Laird Technologies BMI-S-209-F Shielding Cabinet Two Piece SMD 29.36x18.50mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 29.36 y_part_size: 18.50 x_pad_spacer: [1.9, 4.1, 7.9, 10.1, 15.08] y_pad_spacer: [1.9, 4.1, 9.65] x_pad_mirror: True y_pad_mirror: True # page 17 Laird_Technologies_BMI-S-210-F_44.00x30.50mm: description: "Laird Technologies BMI-S-210-F Shielding Cabinet Two Piece SMD 44.00x30.50mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 44.0 y_part_size: 30.5 x_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 16.9, 19.1, 22.4] y_pad_spacer: [1.1, 4.9, 7.1, 10.9, 13.1, 15.65] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_BMI-S-230-F_50.8x38.1mm: description: "Laird Technologies BMI-S-230-F Shielding Cabinet Two Piece SMD 50.8x38.1mm" datasheet: "https://media.digikey.com/pdf/Data%20Sheets/Laird%20Technologies/BMI-S-230-F_Dwg.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 50.8 y_part_size: 38.1 x_pad_spacer: [1.9, 4.1, 7.9, 10.1, 13.9, 16.1, 19.9, 22.1, 25.8] y_pad_spacer: [1.9, 4.1, 7.9, 10.1, 13.9, 16.1, 19.45] x_pad_mirror: True y_pad_mirror: True # page 19 Laird_Technologies_97-2002_25.40x25.40mm: description: "Laird Technologies 97-2002 EZ PEEL Shielding Cabinet One Piece SMD 25.40x25.40mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 0.38 # TODO: add solder mask? x_part_size: 25.40 y_part_size: 25.40 x_pad_spacer: [12.825] y_pad_spacer: [12.825] x_pad_mirror: True y_pad_mirror: True Laird_Technologies_97-2003_12.70x13.37mm: description: "Laird Technologies 97-2003 EZ PEEL Shielding Cabinet One Piece SMD 12.70x13.37mm" datasheet: "http://cdn.lairdtech.com/home/brandworld/files/Board%20Level%20Shields%20Catalog%20Download.pdf" courtjard: 0.25 pads_width: 0.38 # TODO: add solder mask? x_part_size: 12.70 y_part_size: 13.37 x_pad_spacer: [6.475] y_pad_spacer: [6.96] x_pad_mirror: True y_pad_mirror: True # TODO: 97-2004 # TODO: 97-2005 ================================================ FILE: scripts/Shielding/smd_shielding.py ================================================ #!/usr/bin/env python import sys import os import argparse import yaml sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA # https://stackoverflow.com/questions/4265546/python-round-to-nearest-05 def round_to(n, precision): correction = 0.5 if n >= 0 else -0.5 return int(n/precision+correction) * precision def calculate_pad_spacer(pad_spacer, mirror_spacer): pad_spacer_pos = [] if mirror_spacer: for spacer in reversed(pad_spacer): pad_spacer_pos.append(spacer * -1) pad_spacer_pos += pad_spacer return pad_spacer_pos def create_smd_shielding(name, **kwargs): kicad_mod = Footprint(name) # init kicad footprint kicad_mod.setDescription(kwargs['description']) kicad_mod.setTags('Shielding Cabinet') kicad_mod.setAttribute('smd') kicad_mod.append(Model(filename="${KISYS3DMOD}/RF_Shielding.3dshapes/" + name + ".wrl")) # do some pre calculations # TODO: when mirror=False, array has to have even number of array elements x_pad_positions = calculate_pad_spacer(kwargs['x_pad_spacer'], kwargs.get('x_pad_mirror', True)) y_pad_positions = calculate_pad_spacer(kwargs['y_pad_spacer'], kwargs.get('y_pad_mirror', True)) x_pad_min = min(x_pad_positions) x_pad_max = max(x_pad_positions) y_pad_min = min(y_pad_positions) y_pad_max = max(y_pad_positions) x_pad_min_center = x_pad_min + kwargs['pads_width']/2. x_pad_max_center = x_pad_max - kwargs['pads_width']/2. y_pad_min_center = y_pad_min + kwargs['pads_width']/2. y_pad_max_center = y_pad_max - kwargs['pads_width']/2. x_part_min = -kwargs['x_part_size'] / 2. x_part_max = kwargs['x_part_size'] / 2. y_part_min = -kwargs['y_part_size'] / 2. y_part_max = kwargs['y_part_size'] / 2. # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, y_pad_min - kwargs['courtjard'] - 0.75], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=name, at=[0, y_pad_max + kwargs['courtjard'] + 0.75], layer='F.Fab')) kicad_mod.append(Text(type='user', text='%R', at=[0, 0], layer='F.Fab')) # create courtyard x_courtjard_min = round_to(x_pad_min - kwargs['courtjard'], 0.05) x_courtjard_max = round_to(x_pad_max + kwargs['courtjard'], 0.05) y_courtjard_min = round_to(y_pad_min - kwargs['courtjard'], 0.05) y_courtjard_max = round_to(y_pad_max + kwargs['courtjard'], 0.05) kicad_mod.append(RectLine(start=[x_courtjard_min, y_courtjard_min], end=[x_courtjard_max, y_courtjard_max], layer='F.CrtYd')) # create inner courtyard pad_width = kwargs['pads_width'] x_courtjard_min = round_to(x_pad_min + pad_width + kwargs['courtjard'], 0.05) x_courtjard_max = round_to(x_pad_max - pad_width - kwargs['courtjard'], 0.05) y_courtjard_min = round_to(y_pad_min + pad_width + kwargs['courtjard'], 0.05) y_courtjard_max = round_to(y_pad_max - pad_width - kwargs['courtjard'], 0.05) kicad_mod.append(RectLine(start=[x_courtjard_min, y_courtjard_min], end=[x_courtjard_max, y_courtjard_max], layer='F.CrtYd')) # create Fabriaction Layer kicad_mod.append(RectLine(start=[x_part_min, y_part_min], end=[x_part_max, y_part_max], layer='F.Fab')) # all pads have this kwargs, so we only write them one general_kwargs = {'number': 1, 'type': Pad.TYPE_SMT, 'shape': Pad.SHAPE_RECT, 'layers': ['F.Cu', 'F.Mask', 'F.Paste']} # create edge pads kicad_mod.append(Pad(at=[x_pad_min_center, y_pad_min_center], size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs)) kicad_mod.append(Pad(at=[x_pad_max_center, y_pad_min_center], size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs)) kicad_mod.append(Pad(at=[x_pad_max_center, y_pad_max_center], size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs)) kicad_mod.append(Pad(at=[x_pad_min_center, y_pad_max_center], size=[kwargs['pads_width'], kwargs['pads_width']], **general_kwargs)) # iterate pairwise over pads for pad_start, pad_end in zip(x_pad_positions[0::2], x_pad_positions[1::2]): if pad_start == x_pad_min: pad_start += kwargs['pads_width'] if pad_end == x_pad_max: pad_end -= kwargs['pads_width'] kicad_mod.append(Pad(at=[(pad_start+pad_end)/2., y_pad_min_center], size=[abs(pad_start-pad_end), kwargs['pads_width']], **general_kwargs)) kicad_mod.append(Pad(at=[(pad_start+pad_end)/2., y_pad_max_center], size=[abs(pad_start-pad_end), kwargs['pads_width']], **general_kwargs)) for pad_start, pad_end in zip(y_pad_positions[0::2], y_pad_positions[1::2]): if pad_start == y_pad_min: pad_start += kwargs['pads_width'] if pad_end == y_pad_max: pad_end -= kwargs['pads_width'] kicad_mod.append(Pad(at=[x_pad_min_center, (pad_start+pad_end)/2.], size=[kwargs['pads_width'], abs(pad_start-pad_end)], **general_kwargs)) kicad_mod.append(Pad(at=[x_pad_max_center, (pad_start+pad_end)/2.], size=[kwargs['pads_width'], abs(pad_start-pad_end)], **general_kwargs)) # iterate pairwise over pads for silk screen for pad_start, pad_end in zip(x_pad_positions[1::2], x_pad_positions[2::2]): pad_start += 0.3 pad_end -= 0.3 kicad_mod.append(Line(start=[pad_start, y_part_min - 0.15], end=[pad_end, y_part_min - 0.15], layer='F.SilkS')) kicad_mod.append(Line(start=[pad_start, y_part_max + 0.15], end=[pad_end, y_part_max + 0.15], layer='F.SilkS')) for pad_start, pad_end in zip(y_pad_positions[1::2], y_pad_positions[2::2]): pad_start += 0.3 pad_end -= 0.3 # check if line has relevant length if pad_end - pad_start < 0.5: continue kicad_mod.append(Line(start=[x_part_min - 0.15, pad_start], end=[x_part_min - 0.15, pad_end], layer='F.SilkS')) kicad_mod.append(Line(start=[x_part_max + 0.15, pad_start], end=[x_part_max + 0.15, pad_end], layer='F.SilkS')) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{name}.kicad_mod'.format(name=name)) def parse_and_execute_yml_file(filepath): with open(filepath, 'r') as stream: try: yaml_parsed = yaml.safe_load(stream) for footprint in yaml_parsed: print("generate {name}.kicad_mod".format(name=footprint)) create_smd_shielding(footprint, **yaml_parsed.get(footprint)) except yaml.YAMLError as exc: print(exc) if __name__ == "__main__": parser = argparse.ArgumentParser(description='Parse *.kicad_mod.yml file(s) and create matching footprints') parser.add_argument('files', metavar='file', type=str, nargs='+', help='yml-files to parse') #parser.add_argument('-v', '--verbose', help='show more information when creating footprint', action='store_true') # TODO: allow writing into sub file args = parser.parse_args() for filepath in args.files: parse_and_execute_yml_file(filepath) ================================================ FILE: scripts/Shielding/wuerth_electronic_smd_shielding.py ================================================ #!/usr/bin/env python import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA def create_shielding(name, outer_size, size, attachment_width, attachment_length, attachment_positions, outer_attachment_length): kicad_mod = Footprint(name) # init kicad footprint kicad_mod.setDescription('WE-SHC Shielding Cabinet SMD {size}x{size}mm'.format(size=size)) kicad_mod.setTags('Shielding Cabinet') kicad_mod.setAttribute('smd') # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, -outer_size / 2. - 1], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=name, at=[0, outer_size / 2. + 1], layer='F.Fab')) # create courtyard kicad_mod.append(RectLine(start=[-outer_size / 2. - 0.25, -outer_size / 2. - 0.25], end=[outer_size / 2. + 0.25, outer_size / 2. + 0.25], layer='F.CrtYd')) # create Fabriaction Layer kicad_mod.append(RectLine(start=[-size / 2., -size / 2.], end=[size / 2., size / 2.], layer='F.Fab')) outer_pointing_pos = outer_size / 2. - attachment_width / 2. general_kwargs = {'number': 1, 'type': Pad.TYPE_SMT, 'shape': Pad.SHAPE_RECT, 'layers': ['F.Cu', 'F.Mask']} vertical_kwargs = {'number': 1, 'type': Pad.TYPE_SMT, 'shape': Pad.SHAPE_RECT, 'size': [attachment_width, attachment_length], 'layers': ['F.Cu', 'F.Mask']} horizontal_kwargs = {'number': 1, 'type': Pad.TYPE_SMT, 'shape': Pad.SHAPE_RECT, 'size': [attachment_length, attachment_width], 'layers': ['F.Cu', 'F.Mask']} # create inner pads for position in attachment_positions: kicad_mod.append(Pad(at=[outer_pointing_pos, position / 2.], **vertical_kwargs)) kicad_mod.append(Pad(at=[outer_pointing_pos, -position / 2.], **vertical_kwargs)) kicad_mod.append(Pad(at=[-outer_pointing_pos, position / 2.], **vertical_kwargs)) kicad_mod.append(Pad(at=[-outer_pointing_pos, -position / 2.], **vertical_kwargs)) kicad_mod.append(Pad(at=[position / 2., outer_pointing_pos], **horizontal_kwargs)) kicad_mod.append(Pad(at=[position / 2., -outer_pointing_pos], **horizontal_kwargs)) kicad_mod.append(Pad(at=[-position / 2., outer_pointing_pos], **horizontal_kwargs)) kicad_mod.append(Pad(at=[-position / 2., -outer_pointing_pos], **horizontal_kwargs)) # create edge pads kicad_mod.append(Pad(at=[outer_pointing_pos, outer_pointing_pos], size=[attachment_width, attachment_width], **general_kwargs)) kicad_mod.append(Pad(at=[outer_pointing_pos, -outer_pointing_pos], size=[attachment_width, attachment_width], **general_kwargs)) kicad_mod.append(Pad(at=[-outer_pointing_pos, outer_pointing_pos], size=[attachment_width, attachment_width], **general_kwargs)) kicad_mod.append(Pad(at=[-outer_pointing_pos, -outer_pointing_pos], size=[attachment_width, attachment_width], **general_kwargs)) inner_edge_pos = outer_size / 2 - attachment_width - (outer_attachment_length - attachment_width) / 2. inner_edge_length = outer_attachment_length-attachment_width kicad_mod.append(Pad(at=[inner_edge_pos, outer_pointing_pos], size=[inner_edge_length, attachment_width], **general_kwargs)) kicad_mod.append(Pad(at=[inner_edge_pos, -outer_pointing_pos], size=[inner_edge_length, attachment_width], **general_kwargs)) kicad_mod.append(Pad(at=[-inner_edge_pos, outer_pointing_pos], size=[inner_edge_length, attachment_width], **general_kwargs)) kicad_mod.append(Pad(at=[-inner_edge_pos, -outer_pointing_pos], size=[inner_edge_length, attachment_width], **general_kwargs)) kicad_mod.append(Pad(at=[outer_pointing_pos, inner_edge_pos], size=[attachment_width, inner_edge_length], **general_kwargs)) kicad_mod.append(Pad(at=[outer_pointing_pos, -inner_edge_pos], size=[attachment_width, inner_edge_length], **general_kwargs)) kicad_mod.append(Pad(at=[-outer_pointing_pos, inner_edge_pos], size=[attachment_width, inner_edge_length], **general_kwargs)) kicad_mod.append(Pad(at=[-outer_pointing_pos, -inner_edge_pos], size=[attachment_width, inner_edge_length], **general_kwargs)) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{name}.kicad_mod'.format(name=name)) if __name__ == '__main__': # http://katalog.we-online.com/pbs/datasheet/36103205.pdf create_shielding('Würth_36103205_20x20mm', 21.5, 20, 1, 2.6, [7.5], 3.3) # http://katalog.we-online.com/pbs/datasheet/36103255.pdf create_shielding('Würth_36103255_25x25mm', 26.5, 25, 1, 2.6, [5.1, 12.5], 3.3) # http://katalog.we-online.com/pbs/datasheet/36103305.pdf create_shielding('Würth_36103305_30x30mm', 31.5, 30, 1, 2.6, [7.5, 17.5], 3.3) # http://katalog.we-online.com/pbs/datasheet/36103505.pdf create_shielding('Würth_36103505_50x50mm', 51.5, 50, 1, 2.6, [7.5, 17.5, 27.5, 37.5], 3.3) # http://katalog.we-online.com/pbs/datasheet/36103605.pdf create_shielding('Würth_36103605_60x60mm', 61.5, 60, 1, 2.6, [7.5, 17.5, 27.5, 37.5, 47.5], 3.5) ================================================ FILE: scripts/Shielding/wuerth_electronic_tht_shielding.py ================================================ #!/usr/bin/env python import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA def create_shielding(name, outer_size, size, attachment_drill, attachment_diameter, attachment_positions): attachment_positions = sorted(attachment_positions) kicad_mod = Footprint(name) # init kicad footprint kicad_mod.setDescription('WE-SHC Shielding Cabinet THT {size}x{size}mm'.format(size=size)) kicad_mod.setTags('Shielding Cabinet') courtjard_size = outer_size / 2. + attachment_diameter / 2. + 0.25 # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0, -courtjard_size - 1], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=name, at=[0, courtjard_size + 1], layer='F.Fab')) # create courtyard kicad_mod.append(RectLine(start=[-courtjard_size, -courtjard_size], end=[courtjard_size, courtjard_size], layer='F.CrtYd')) # create Fabriaction Layer kicad_mod.append(RectLine(start=[-size / 2., -size / 2.], end=[size / 2., size / 2.], layer='F.Fab')) general_kwargs = {'number': 1, 'type': Pad.TYPE_THT, 'shape': Pad.SHAPE_CIRCLE, 'size': [attachment_diameter, attachment_diameter], 'drill': attachment_drill, 'layers': ['*.Cu', '*.Mask']} # create pads for position in attachment_positions: kicad_mod.append(Pad(at=[outer_size / 2., position / 2.], **general_kwargs)) kicad_mod.append(Pad(at=[-outer_size / 2., position / 2.], **general_kwargs)) kicad_mod.append(Pad(at=[position / 2., outer_size / 2.], **general_kwargs)) kicad_mod.append(Pad(at=[position / 2., -outer_size / 2.], **general_kwargs)) if position != 0. or 2*outer_size == 2*position: kicad_mod.append(Pad(at=[outer_size / 2., -position / 2.], **general_kwargs)) kicad_mod.append(Pad(at=[-outer_size / 2., -position / 2.], **general_kwargs)) kicad_mod.append(Pad(at=[-position / 2., outer_size / 2.], **general_kwargs)) kicad_mod.append(Pad(at=[-position / 2., -outer_size / 2.], **general_kwargs)) # create silk screen silk_padding = 0.2 silk_outline = size / 2. + silk_padding pad_padding = 0.4 if attachment_positions[0] != 0.: line_end = attachment_positions[0] / 2. - attachment_diameter / 2. - pad_padding kicad_mod.append(Line(start=[silk_outline, line_end], end=[silk_outline, -line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[-silk_outline, -line_end], end=[-silk_outline, line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[line_end, silk_outline], end=[-line_end, silk_outline], layer='F.SilkS')) kicad_mod.append(Line(start=[line_end, -silk_outline], end=[-line_end, -silk_outline], layer='F.SilkS')) for begin, end in zip(attachment_positions, attachment_positions[1:]): line_begin = begin / 2. + attachment_diameter / 2. + pad_padding line_end = end / 2. - attachment_diameter / 2. - pad_padding kicad_mod.append(Line(start=[silk_outline, line_begin], end=[silk_outline, line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[silk_outline, -line_begin], end=[silk_outline, -line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[-silk_outline, line_begin], end=[-silk_outline, line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[-silk_outline, -line_begin], end=[-silk_outline, -line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[line_begin, silk_outline], end=[line_end, silk_outline], layer='F.SilkS')) kicad_mod.append(Line(start=[line_begin, -silk_outline], end=[line_end, -silk_outline], layer='F.SilkS')) kicad_mod.append(Line(start=[-line_begin, silk_outline], end=[-line_end, silk_outline], layer='F.SilkS')) kicad_mod.append(Line(start=[-line_begin, -silk_outline], end=[-line_end, -silk_outline], layer='F.SilkS')) if attachment_positions[-1] != outer_size: line_begin = attachment_positions[-1] / 2. + attachment_diameter / 2. + pad_padding line_end = outer_size / 2. + silk_padding kicad_mod.append(Line(start=[silk_outline, line_begin], end=[silk_outline, line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[silk_outline, -line_begin], end=[silk_outline, -line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[-silk_outline, line_begin], end=[-silk_outline, line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[-silk_outline, -line_begin], end=[-silk_outline, -line_end], layer='F.SilkS')) kicad_mod.append(Line(start=[line_begin, silk_outline], end=[line_end, silk_outline], layer='F.SilkS')) kicad_mod.append(Line(start=[line_begin, -silk_outline], end=[line_end, -silk_outline], layer='F.SilkS')) kicad_mod.append(Line(start=[-line_begin, silk_outline], end=[-line_end, silk_outline], layer='F.SilkS')) kicad_mod.append(Line(start=[-line_begin, -silk_outline], end=[-line_end, -silk_outline], layer='F.SilkS')) # fix KLC issue 6.3 # kicad_mod.insert(Translation(outer_size / 2., attachment_positions[-1] / 2.)) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{name}.kicad_mod'.format(name=name)) if __name__ == '__main__': # http://katalog.we-online.de/pbs/datasheet/36503205.pdf create_shielding('Würth_36503205_20x20mm', 20.5, 20.5, 1.1, 1.7, [5.08, 15.24]) # http://katalog.we-online.de/pbs/datasheet/36503255.pdf create_shielding('Würth_36503255_25x25mm', 25.5, 25.5, 1.1, 1.7, [0, 10.16, 20.32]) # http://katalog.we-online.de/pbs/datasheet/36503305.pdf create_shielding('Würth_36503305_30x30mm', 30.5, 30.5, 1.1, 1.7, [5.08, 15.24, 25.40]) # http://katalog.we-online.de/pbs/datasheet/36503505.pdf create_shielding('Würth_36503505_50x50mm', 50.5, 50.5, 1.1, 1.7, [5.08, 15.24, 25.40, 35.56, 45.72]) # http://katalog.we-online.de/pbs/datasheet/36503605.pdf create_shielding('Würth_36503605_60x60mm', 60.5, 60.5, 1.1, 1.7, [5.08, 15.24, 25.40, 35.56, 45.72, 55.88]) ================================================ FILE: scripts/Shielding/wuerth_smd_shielding.kicad_mod.yaml ================================================ Würth_36103205_20x20mm: description: "WE-SHC Shielding Cabinet SMD 20x20mm" datasheet: "http://katalog.we-online.com/pbs/datasheet/36103205.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 20 y_part_size: 20 x_pad_spacer: [2.45, 5.05, 7.45, 10.75] y_pad_spacer: [2.45, 5.05, 7.45, 10.75] x_pad_mirror: True y_pad_mirror: True Würth_36103255_25x25mm: description: "WE-SHC Shielding Cabinet SMD 25x25mm" datasheet: "http://katalog.we-online.com/pbs/datasheet/36103255.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 25 y_part_size: 25 x_pad_spacer: [2.55, 4.95, 7.55, 9.95, 13.25] y_pad_spacer: [2.55, 4.95, 7.55, 9.95, 13.25] x_pad_mirror: True y_pad_mirror: True Würth_36103305_30x30mm: description: "WE-SHC Shielding Cabinet SMD 30x30mm" datasheet: "http://katalog.we-online.com/pbs/datasheet/36103305.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 30 y_part_size: 30 x_pad_spacer: [2.45, 5.05, 7.45, 10.05, 12.45, 15.75] y_pad_spacer: [2.45, 5.05, 7.45, 10.05, 12.45, 15.75] x_pad_mirror: True y_pad_mirror: True Würth_36103505_50x50mm: description: "WE-SHC Shielding Cabinet SMD 50x50mm" datasheet: "http://katalog.we-online.com/pbs/datasheet/36103505.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 50 y_part_size: 50 x_pad_spacer: [2.45, 5.05, 7.45, 10.05, 12.45, 15.05, 17.45, 20.05, 22.45, 25.75] y_pad_spacer: [2.45, 5.05, 7.45, 10.05, 12.45, 15.05, 17.45, 20.05, 22.45, 25.75] x_pad_mirror: True y_pad_mirror: True Würth_36103605_60x60mm: description: "WE-SHC Shielding Cabinet SMD 60x60mm" datasheet: "http://katalog.we-online.com/pbs/datasheet/36103605.pdf" courtjard: 0.25 pads_width: 1 x_part_size: 60 y_part_size: 60 x_pad_spacer: [2.45, 5.05, 7.45, 10.05, 12.45, 15.05, 17.45, 20.05, 22.45, 25.05, 27.25, 30.75] y_pad_spacer: [2.45, 5.05, 7.45, 10.05, 12.45, 15.05, 17.45, 20.05, 22.45, 25.05, 27.25, 30.75] x_pad_mirror: True y_pad_mirror: True ================================================ FILE: scripts/Socket/3M_Textool.py ================================================ #!/usr/bin/env python3 import sys import os # load parent path of KicadModTree sys.path.append(os.path.join(sys.path[0], "..", "..")) from KicadModTree import * def roundCrtYd(x): sign = x / abs(x) return int((x + 0.0001 * sign) * 100) / 100.0 def textool(args): name = args["name"] nPads = args["n_pads"] dimA = args["a"] dimB = args["b"] dimC = args["c"] mils = args["c_mils"] lever = args["lever"] minWidth = args["min"] maxWidth = args["max"] widths = "_W" + str(minWidth) for i in range(0, 15): w = i * 2.54 if w > minWidth and w < maxWidth: widths = widths + "_W" + str(w) widths = widths + "_W" + str(maxWidth) footprint_name = "DIP_Socket-" + str(nPads) + widths + "_3M_" + name f = Footprint(footprint_name) f.setDescription("3M " + str(nPads) + "-pin zero insertion force socket, through-hole, row spacing " + str(dimC) + " mm (" + str(mils) + " mils), http://multimedia.3m.com/mws/media/494546O/3mtm-dip-sockets-100-2-54-mm-ts0365.pdf") f.setTags("THT DIP DIL ZIF " + str(dimC) + "mm " + str(mils) + "mil Socket") f.append(Model(filename="${KISYS3DMOD}/Socket.3dshapes/" + footprint_name + ".wrl", at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) pitch = 2.54 d = [1.0, 1.0] p = [2.0, 1.44] r1 = 0.9 r2 = 2.55 s1 = [0.6, 0.6] s2 = [1.0, 1.0] t1 = 0.09 t2 = 0.15 wCrtYd = 0.05 wFab = 0.1 wSilkS = 0.12 silk = 0.1 crtYd = 0.5 xLeftPads = 0.0 xLeftFab = xLeftPads - (dimB - dimC) / 2 xLeftSilk = xLeftFab - silk xLeftCrtYd = roundCrtYd(xLeftFab - crtYd) xRightPads = dimC xRightFab = xLeftFab + dimB xRightSilk = xRightFab + silk xRightCrtYd = roundCrtYd(xRightFab + crtYd) xLeftLever = -5.0 xP1Ind = -4.95 x06 = -3.7 x07 = -3.5 x08 = -3.2 x09 = -2.85 x10 = -1.9 x11 = -1.7 x12 = -1.65 xRightLever = -0.4 xMiddle = dimC / 2 xLeftLeverCrtYd = roundCrtYd(xLeftLever - crtYd) xRightLeverCrtYd = roundCrtYd(xRightLever + crtYd) yTopPads = 0.0 yTopFab = -10.56 yTopSilk = yTopFab - silk yTopCrtYd = roundCrtYd(yTopFab - crtYd) yBottomFab = yTopFab + dimA yBottomSilk = yBottomFab + silk yBottomCrtYd = roundCrtYd(yBottomFab + crtYd) # These four are the lever yTopLever = yTopFab - lever # -25.4 y02 = yTopLever + 1.4 # -24.0 y03 = yTopLever + 5.0 # -20.4 y04 = yTopLever + 7.0 # -18.4 yRef = yTopFab - 1 yValue = yBottomFab + 1 yFabRef = (yTopFab + yBottomFab) / 2 y09 = -9.75 y10 = -9.4 y11 = -8.8 y12 = -8.4 y13 = -6.35 yBottomLever = -3.9 yFirstLine = -1.27 ySecondLine = 1.27 yTopLeverCrtYd = roundCrtYd(yTopLever - crtYd) yBottomLeverCrtYd = roundCrtYd(yBottomLever + crtYd) # Text f.append(Text(type="reference", text="REF**", at=[xMiddle, yRef], layer="F.SilkS", size=s2, thickness=t2)) f.append(Text(type="value", text=footprint_name, at=[xMiddle, yValue], layer="F.Fab", size=s1, thickness=t1)) f.append(Text(type="user", text="%R", at=[xMiddle, yFabRef], layer="F.Fab", size=s2, thickness=t2)) # Courtyard f.append(PolygoneLine(polygone=[[xLeftLeverCrtYd, yTopLeverCrtYd], [xRightLeverCrtYd, yTopLeverCrtYd], [xRightLeverCrtYd, yTopCrtYd], [xRightCrtYd, yTopCrtYd], [xRightCrtYd, yBottomCrtYd], [xLeftCrtYd, yBottomCrtYd], [xLeftCrtYd, yBottomLeverCrtYd], [xLeftLeverCrtYd, yBottomLeverCrtYd], [xLeftLeverCrtYd, yTopLeverCrtYd]], layer="F.CrtYd", width=wCrtYd)) # Fab Lever f.append(PolygoneLine(polygone=[[xLeftLever, y02], [x06, yTopLever], [x11, yTopLever], [xRightLever, y02], [xLeftLever, y02], [xLeftLever, y03], [xRightLever, y03], [xRightLever, y02]], layer="F.Fab", width=wFab)) f.append(Line(start=[xLeftLever, y03], end=[x07, y04], layer="F.Fab", width=wFab)) f.append(Line(start=[xRightLever, y03], end=[x10, y04], layer="F.Fab", width=wFab)) f.append(PolygoneLine(polygone=[[x07, y09], [x07, y04], [x10, y04], [x10, yTopFab]], layer="F.Fab", width=wFab)) # Fab Outline f.append(PolygoneLine(polygone=[[xRightFab, yBottomFab], [xLeftFab, yBottomFab], [xLeftFab, y10], [x09, yTopFab], [xRightFab, yTopFab], [xRightFab, yBottomFab]], layer="F.Fab", width=wFab)) # Silk Outline f.append(PolygoneLine(polygone=[[xLeftSilk, yBottomLever], [xLeftSilk, yBottomSilk], [xRightSilk, yBottomSilk], [xRightSilk, yTopSilk], [xLeftSilk, yTopSilk], [xLeftSilk, y11]], layer="F.SilkS", width=wSilkS)) # Silk Lever f.append(Line(start=[x12, yTopSilk], end=[x12, y12], layer="F.SilkS", width=wSilkS)) f.append(Circle(center=[x08, y13], radius=r2, layer="F.SilkS", width=wSilkS)) f.append(Circle(center=[x08, y13], radius=r1, layer="F.SilkS", width=wSilkS)) # Silk Pin 1 Indicator f.append(Line(start=[xP1Ind, ySecondLine], end=[xP1Ind, yFirstLine], layer="F.SilkS", width=wSilkS)) # Pads pShape = Pad.SHAPE_RECT for i in range(0, nPads >> 1): y = yTopPads + i * pitch f.append(Pad(number=str(i+1), type=Pad.TYPE_THT, shape=pShape, at=[xLeftPads, y], size=p, layers=Pad.LAYERS_THT, drill=d)) pShape = Pad.SHAPE_OVAL f.append(Pad(number=str(nPads-i), type=Pad.TYPE_THT, shape=pShape, at=[xRightPads, y], size=p, layers=Pad.LAYERS_THT, drill=d)) file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(textool) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("n_pads", type=int, required=True) parser.add_parameter("a", type=float, required=True) parser.add_parameter("b", type=float, required=True) parser.add_parameter("c", type=float, required=True) parser.add_parameter("c_mils", type=int, required=True) parser.add_parameter("lever", type=float, required=False, default=12.3) parser.add_parameter("min", type=float, required=True) parser.add_parameter("max", type=float, required=True) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/Socket/3M_Textool.yaml ================================================ 214-3339-00-0602J: n_pads: 14 a: 33.0 b: 15.2 c: 7.62 c_mils: 300 min: 4.3 max: 10.9 216-3340-00-0602J: n_pads: 16 a: 35.3 b: 15.2 c: 7.62 c_mils: 300 min: 4.3 max: 10.9 218-3341-00-0602J: n_pads: 18 a: 37.8 b: 15.2 c: 7.62 c_mils: 300 min: 4.3 max: 10.9 220-3342-00-0602J: n_pads: 20 a: 40.4 b: 15.2 c: 7.62 c_mils: 300 min: 4.3 max: 10.9 222-3343-00-0602J: n_pads: 22 a: 42.9 b: 17.8 c: 10.16 c_mils: 400 min: 6.9 max: 13.5 224-1275-00-0602J: n_pads: 24 a: 45.3 b: 22.9 c: 15.24 c_mils: 600 min: 11.9 max: 18.5 224-5248-00-0602J: n_pads: 24 a: 45.5 b: 15.2 c: 7.62 c_mils: 300 min: 4.3 max: 10.9 228-1277-00-0602J: n_pads: 28 a: 50.4 b: 22.9 c: 15.24 c_mils: 600 min: 11.9 max: 18.5 228-4817-00-0602J: n_pads: 28 a: 50.5 b: 17.8 c: 10.16 c_mils: 400 min: 6.9 max: 13.5 232-1285-00-0602J: n_pads: 32 a: 55.5 b: 22.9 c: 15.24 c_mils: 600 min: 11.9 max: 18.5 240-1280-00-0602J: n_pads: 40 a: 65.6 b: 22.9 c: 15.24 c_mils: 600 min: 11.9 max: 18.5 240-3639-00-0602J: n_pads: 40 a: 65.5 b: 33.0 c: 25.40 c_mils: 1000 min: 22.1 max: 28.7 242-1281-00-0602J: n_pads: 42 a: 68.2 b: 22.9 c: 15.24 c_mils: 600 min: 11.9 max: 18.5 ================================================ FILE: scripts/TerminalBlock_4Ucon/make_TerminalBlock_4Ucon.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note="script-generated using https://github.com/pointhi/kicad-footprint-generator/scripts/TerminalBlock_4Ucon"; classname="TerminalBlock_4Ucon" pins=[2,3,4,5,6,7,8,9,10,11,12,13,14,15] rm=3.5 package_height=8.3 leftbottom_offset=[2.25,package_height-3.7] ddrill=1.3 pad=[2.6,2.6] bevel_height=[3.5] opening=[2.8,3.75] opening_yoffset=package_height-0.7-opening[1] secondHoleDiameter=2 secondHoleOffset=[0,-(3.7-2.1)] thirdHoleDiameter=0 thirdHoleOffset=[0,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3] nibbleSize=[] nibblePos=[] for pi in range(0,len(pins)): p=pins[pi]; itemno=10691+p; name="{0}".format(itemno); webpage="http://www.4uconnector.com/online/object/4udrawing/{0}.pdf".format(itemno); classname_description="Terminal Block 4Ucon ItemNo. {0}".format(itemno); footprint_name="TerminalBlock_4Ucon_1x{2:02}_P{1:3.2f}mm_Vertical".format(name, rm, p) makeTerminalBlockVertical(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=[2,3,4,5,6,7,8,9,10,11,12,13,14,15] itemnos=[19963,20193,20001,20223,19964,10684,19965,10686,10687,10688,10689,10690,10691,10692] rm=3.5 package_height=7 leftbottom_offset=[2.1, package_height-3.4] ddrill=1.2 pad=[2.4,2.4] screw_diameter=2.75 bevel_height=[1.5] slit_screw=False screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.8] nibbleSize=[] nibblePos=[] for pi in range(0,len(pins)): p=pins[pi]; itemno=itemnos[pi]; name="{0}".format(itemno); webpage="http://www.4uconnector.com/online/object/4udrawing/{0}.pdf".format(itemno); classname_description="Terminal Block 4Ucon ItemNo. {0}".format(itemno); footprint_name="TerminalBlock_4Ucon_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/TerminalBlock_Altech/Altech.py ================================================ #!/usr/bin/env python3 import sys import os import math sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree import argparse import yaml from KicadModTree import * sys.path.append(os.path.join(sys.path[0], "..", "tools")) # load parent path of tools sys.path.append(os.path.join(sys.path[0], "..", "general")) # load parent path of tools from StandardBox import * def qfn(args): extraffablines = [] name = args["name"] description = args["description"] datasheet = args["datasheet"] tags = args["tags"] manufacture = args["manufacture"] serie = args["serie"] W = args["W"] H = args["H"] WD = args["WD"] A1 = args["A1"] pinnumbers = args["pin_number"] PE = args["PE"] PS = args["PS"] PD = args["PD"] PL = args["PL"] PF = args["PF"] SW = args["SW"] DD = args["DD"] PD = args["PD"] rotation = args["rotation"] dest_dir_3D_prefix = args["dest_dir_3D_prefix"] for pinnumber in pinnumbers: footprint_name = '' footprint_name = footprint_name + manufacture + '_' + serie footprint_name = footprint_name + '_1x' + '{:02d}'.format(pinnumber) footprint_name = footprint_name + '_P' + '{:.2f}'.format(PS) + "mm" footprint_name = footprint_name + '_45-Degree' f = Footprint(footprint_name) file3Dname = "${KISYS3DMOD}/" + dest_dir_3D_prefix + "/" + footprint_name + ".wrl" words = footprint_name.split("_") if words[-1].lower().startswith('handsolder'): words[-1] = '' ff = '_'.join(words) file3Dname = "${KISYS3DMOD}/" + dest_dir_3D_prefix + "/" + ff + ".wrl" lw = ((2.0 * PE) + ((pinnumber - 1) * PS)) at = [0.0 - PE, W - WD] size = [lw, W] extratexts = None SmdTht = None pins = [] dx = 0.0 for ii in range(1, pinnumber + 1): pins.append(["tht", str(ii), dx, 0.0, PD, PD, DD]) dx = dx + PS f.append(StandardBox(footprint=f, description=description, datasheet=datasheet, at=at, size=size, tags=tags, SmdTht=SmdTht, extratexts=extratexts, pins=pins, file3Dname=file3Dname )) # # file_handler = KicadFileHandler(f) file_handler.writeFile(footprint_name + ".kicad_mod") if __name__ == '__main__': parser = ModArgparser(qfn) # the root node of .yml files is parsed as name parser.add_parameter("name", type=str, required=True) parser.add_parameter("description", type=str, required=True) parser.add_parameter("datasheet", type=str, required=True) parser.add_parameter("tags", type=str, required=True) parser.add_parameter("manufacture", type=str, required=True) parser.add_parameter("serie", type=str, required=True) parser.add_parameter("W", type=float, required=True) parser.add_parameter("H", type=float, required=True) parser.add_parameter("WD", type=float, required=True) parser.add_parameter("A1", type=float, required=True) parser.add_parameter("pin_number", type=list, required=True) parser.add_parameter("PE", type=float, required=True) parser.add_parameter("PS", type=float, required=True) parser.add_parameter("PD", type=list, required=True) parser.add_parameter("PL", type=float, required=True) parser.add_parameter("PF", type=str, required=True) parser.add_parameter("SW", type=float, required=True) parser.add_parameter("DD", type=float, required=True) parser.add_parameter("PD", type=float, required=True) parser.add_parameter("rotation", type=str, required=True) parser.add_parameter("dest_dir_3D_prefix", type=str, required=True) # now run our script which handles the whole part of parsing the files parser.run() ================================================ FILE: scripts/TerminalBlock_Altech/Altech.yml ================================================ AK300: description: "Altech AK300 serie terminal block" datasheet: "http://www.altechcorp.com/PDFS/PCBMETRC.PDF" tags: "Altech AK300 serie connector" manufacture: 'Altech' # Model name serie: 'AK300' # Model name W: 12.5 # Package width H: 12.5 # Package height WD: 6.5 # > Y distance form pin center to package edge A1: 0.1 # package board seperation pin_number: [ 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24] # Which pin configuration PE: 2.5 # Distance from edge to pin PS: 5.0 # Distance between pins PD: [1.0, 0.8] # Pin size, [1.0] diameter 1 mm, [1.0, 0.8] rectangle 1.0x0.8 PL: 4.5 # Pin length PF: 'rect' # Pin form 'round' or 'rect' SW: 2.7 # Blender width DD: 1.5 # Drill diameter PD: 3.0 # Pad diameter rotation: 0 # Rotation if required dest_dir_3D_prefix: 'TerminalBlock_Altech.3dshapes' # Destination directory ================================================ FILE: scripts/TerminalBlock_MetzConnect/make_SingleTerminalBlock_MetzConnect.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note="script-generated using https://github.com/pointhi/kicad-footprint-generator/scripts/TerminalBlock_MetzConnect"; classname="TerminalBlock_MetzConnect" block_size=[4,4] block_offset=[0,0] pins=[[1.5,0],[-1.5,0]] ddrill=1.5 pad=[3,3] screw_diameter=3 screw_offset=[0,0] slit_screw=True name="360272" webpage="http://www.metz-connect.com/de/system/files/METZ_CONNECT_U_Contact_Katalog_Anschlusssysteme_fuer_Leiterplatten_DE_31_07_2017_OFF_024803.pdf?language=en page 131" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM2.6".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) block_size=[5,4] block_offset=[0.5,0] name="360273" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM2.6_WireProtection".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) block_size=[5,5] block_offset=[0,0] pins=[[2,0],[-2,0]] ddrill=1.5 pad=[3,3] screw_diameter=4 screw_offset=[0,0] slit_screw=True name="360410" webpage="http://www.metz-connect.com/de/system/files/METZ_CONNECT_U_Contact_Katalog_Anschlusssysteme_fuer_Leiterplatten_DE_31_07_2017_OFF_024803.pdf?language=en page 132" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM3.0".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) name="360381" webpage="http://www.metz-connect.com/de/system/files/METZ_CONNECT_U_Contact_Katalog_Anschlusssysteme_fuer_Leiterplatten_DE_31_07_2017_OFF_024803.pdf?language=en page 133" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM3.0".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) block_size=[6,4] block_offset=[1,0] name="360322" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM3.0_WireProtection".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) block_size=[9, 7.3] block_offset=[0,0] pins=[[2,0],[-2,0]] ddrill=1.5 pad=[3,3] screw_diameter=4 screw_offset=[0,0] slit_screw=True name="360291" webpage="http://www.metz-connect.com/de/system/files/METZ_CONNECT_U_Contact_Katalog_Anschlusssysteme_fuer_Leiterplatten_DE_31_07_2017_OFF_024803.pdf?language=en page 133" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM3.0_Boxed".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) block_size=[9, 7.3] block_offset=[0,0] pins=[[0,0]] ddrill=1.5 pad=[3,3] screw_diameter=4 screw_offset=[0,0] slit_screw=True name="360271" webpage="http://www.metz-connect.com/de/system/files/METZ_CONNECT_U_Contact_Katalog_Anschlusssysteme_fuer_Leiterplatten_DE_31_07_2017_OFF_024803.pdf?language=en page 134" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM3.0_Boxed".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) block_size=[9,9] block_offset=[0,0] pins=[[4,4],[-4,4],[4,-4],[-4,-4]] ddrill=1.6 pad=[3.2,3.2] screw_diameter=7 screw_offset=[0,0] slit_screw=True name="360425" webpage="http://www.metz-connect.com/de/system/files/METZ_CONNECT_U_Contact_Katalog_Anschlusssysteme_fuer_Leiterplatten_DE_31_07_2017_OFF_024803.pdf?language=en page 134" footprint_name="TerminalBlock_MetzConnect_{0}_1x01_Horizontal_ScrewM4.0_Boxed".format(name) classname_description="single screw terminal block Metz Connect {0}".format(name) makeScrewTerminalSingleStd(footprint_name, block_size=block_size, block_offset=block_offset, pins=pins, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, screw_offset=screw_offset, slit_screw=slit_screw, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/TerminalBlock_MetzConnect/make_TerminalBlock_MetzConnect.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note="script-generated using https://github.com/pointhi/kicad-footprint-generator/scripts/TerminalBlock_MetzConnect"; classname="TerminalBlock_MetzConnect" pins=[2,3,4,5,6] rm=5 package_height=12.5 leftbottom_offset=[rm/2, 6.5] ddrill=1.4 pad=[2.7,2.7] screw_diameter=2.2 bevel_height=[5.4,9.2] vsegment_lines_offset=[] opening=[3.5,4] opening_xoffset=0 opening_yoffset=1 opening_elliptic=False secondDrillDiameter=0 secondDrillOffset=[2.5,-5] secondDrillPad=pad secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[1.25,0] fourthHoleDiameter=0 fourthHoleOffset=[1.25,-5.75] fifthHoleDiameter=0 fifthHoleOffset=[1.25,-0.75] secondEllipseSize=[3.6,2.8] secondEllipseOffset=[0,-4.4] fabref_offset=[0,-1] nibbleSize=[] nibblePos=[] for p in pins: name="Type205_RT045{0:02}UBLC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_312051_RT045xxUBLC_OFF-022759T.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, vsegment_lines_offset=vsegment_lines_offset, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, opening_elliptic=opening_elliptic, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, fifthHoleDiameter=fifthHoleDiameter,fifthHoleOffset=fifthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, secondEllipseSize=secondEllipseSize,secondEllipseOffset=secondEllipseOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,6+1) rm=3.81 package_height=7.3 leftbottom_offset=[1.85, 3.6] ddrill=0.7 pad=[1.4,1.4] screw_diameter=2.5 bevel_height=[0.6,1.9,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=[2,0.5] thirdHoleOffset=[0,-(3.6-0.5/2)] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.45] nibbleSize=[] nibblePos=[] for p in pins: name="Type086_RT034{0:02}HBLC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_310861_RT034xxHBLC_OFF-026114K.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,6+1) rm=5.0 package_height=10.5 leftbottom_offset=[2.5, 4] ddrill=1.4 pad=[2.8,2.8] screw_diameter=3.2 bevel_height=[2,package_height-4.5,package_height-3.5] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,4.5] nibbleSize=[] nibblePos=[] for p in pins: name="Type011_RT055{0:02}HBWC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_310111_RT055xxHBLC_OFF-022717S.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,5+1) rm=10 package_height=8.2 leftbottom_offset=[2.9, 4.1] ddrill=1.3 pad=[2.6,2.6] screw_diameter=3 bevel_height=[2,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3] nibbleSize=[] nibblePos=[] for p in pins: name="Type067_RT019{0:02}HDWC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_310671_RT019xxHDWC_OFF-023605N.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,3+1) rm=9.52 package_height=12.5 leftbottom_offset=[4.76, 8] ddrill=1.3 pad=[2.6,2.6] screw_diameter=4 bevel_height=[0.5,4.5,package_height-2] slit_screw=True screw_pin_offset=[0,0.5] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=[2,1] thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3.5] nibbleSize=[] nibblePos=[] for p in pins: name="Type703_RT10N{0:02}HGLU".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_317031_RT10NxxHGLU_OFF-022897S.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,6+1) rm=5.0 package_height=8.3 leftbottom_offset=[2.5, 4] ddrill=1.3 pad=[2.6,2.6] screw_diameter=3 bevel_height=[0.5,2,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=[2,1] thirdHoleOffset=[0,-(4.3-0.5)] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.9] nibbleSize=[] nibblePos=[] for p in pins: name="Type094_RT035{0:02}HBLU".format(p) webpage="http://www.metz-connect.com/ru/system/files/productfiles/Data_sheet_310941_RT035xxHBLU_OFF-022742T.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,6+1) rm=5.08 package_height=8 leftbottom_offset=[2.54, 4] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[2,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3] nibbleSize=[] nibblePos=[] for p in pins: name="Type101_RT016{0:02}HBWC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_311011_RT016xxHBWC_OFF-022771S.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,6+1) rm=3.5 package_height=6.5 leftbottom_offset=[rm/2, 3.7] ddrill=1.2 pad=[2.3,2.3] screw_diameter=2.75 bevel_height=[1.5] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.5] nibbleSize=[] nibblePos=[] for p in pins: name="Type059_RT063{0:02}HBWC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_310591_RT063xxHBWC_OFF-022684T.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,3+1) rm=5.08 package_height=11 leftbottom_offset=[2.54, 5.5] ddrill=1.4 pad=[2.6,2.6] screw_diameter=3.5 bevel_height=[0.5,3,package_height-1.8] slit_screw=True screw_pin_offset=[0,-0.3] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3.5] nibbleSize=[] nibblePos=[] for p in pins: name="Type073_RT026{0:02}HBLU".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_310731_RT026xxHBLU_OFF-022792U.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,3+1) rm=6.35 package_height=12.5 leftbottom_offset=[3.175, 8] ddrill=1.3 pad=[2.5,2.5] screw_diameter=4 bevel_height=[0.5,5.5,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=[2,1] thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3.5] nibbleSize=[] nibblePos=[] for p in pins: name="Type701_RT11L{0:02}HGLU".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_317011_RT11LxxHGLU_OFF-022798U.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,6+1) rm=7.5 package_height=9 leftbottom_offset=[3.75, 4.5] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[2,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[rm/2,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3.5] nibbleSize=[] nibblePos=[] for p in pins: name="Type171_RT137{0:02}HBWC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_311711_RT137xxHBWC_OFF-022811Q.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,6+1) rm=7.5 package_height=11 leftbottom_offset=[3.75, 5.5] ddrill=1.4 pad=[2.6,2.6] screw_diameter=3 bevel_height=[0.6,2.5,package_height-1.9] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[rm/2,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,4] nibbleSize=[] nibblePos=[] for p in pins: name="Type175_RT027{0:02}HBLC".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_311751_RT027xxHBLC_OFF-022814U.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,4+1) rm=5 package_height=8 leftbottom_offset=[2.5,4] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[2,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[rm/2,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3] nibbleSize=[] nibblePos=[] for p in pins: name="Type055_RT015{0:02}HDWU".format(p) webpage="http://www.metz-connect.com/de/system/files/productfiles/Datenblatt_310551_RT015xxHDWU_OFF-022723S.pdf" footprint_name="TerminalBlock_MetzConnect_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block Metz Connect {0}".format(name, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/TerminalBlock_Philmore/make_TerminalBlock_Philmore.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note="script-generated using https://github.com/pointhi/kicad-footprint-generator/scripts/TerminalBlock_Philmore"; classname="TerminalBlock_Philmore" pins=range(2,3+1) rm=5 package_height=10.2 leftbottom_offset=[rm/2, 5.4] ddrill=1.2 pad=[2.4,2.4] screw_diameter=2.75 bevel_height=[0.5,1.6] slit_screw=False screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.5] nibbleSize=[] nibblePos=[] for p in pins: name="TB13{0}".format(p); webpage="http://www.philmore-datak.com/mc/Page%20197.pdf"; classname_description="Terminal Block Philmore ".format(name); footprint_name="TerminalBlock_Philmore_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/TerminalBlock_Phoenix/make_TerminalBlock_Phoenix.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note="script-generated using https://github.com/pointhi/kicad-footprint-generator/scripts/TerminalBlock_Phoenix"; classname="TerminalBlock_Phoenix" pins=range(2,8+1) rm=2.5 package_height=5 leftbottom_offset=[3-0.65, 0.9, 0.65] ddrill=1.2 pad=[2,2] bevel_height=[] opening=[2,1] opening_xoffset=1 opening_yoffset=3.0 secondDrillDiameter=ddrill secondDrillOffset=[0,-3.1] secondDrillPad=pad secondHoleDiameter=2 secondHoleOffset=[-1,-0.5] thirdHoleDiameter=0 thirdHoleOffset=[-1,-1] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,-3.56] nibbleSize=[] nibblePos=[] for p in pins: name="PTSM-0,5-{0}-{1:1.2}-V-THR".format(p,rm); webpage="http://www.produktinfo.conrad.com/datenblaetter/550000-574999/556444-da-01-de-LEITERPLATTENKL__PTSM_0_5__4_2_5_V_THR.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Vertical".format(name, rm, p) makeTerminalBlockVertical(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, opening=opening, ddrill=ddrill, pad=pad, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,8+1) rm=2.5 package_height=10 leftbottom_offset=[2.35, 2.8] ddrill=1.2 pad=[1.8,3] screw_diameter=0 bevel_height=[] slit_screw=False screw_pin_offset=[0,0] secondDrillDiameter=ddrill secondDrillOffset=[0,-5] secondDrillPad=pad secondHoleDiameter=[1,1] secondHoleOffset=[0,6.5] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,0] nibbleSize=[] nibblePos=[] for p in pins: name="PTSM-0,5-{0}-{1:1.2}-H-THR".format(p,rm); webpage="http://www.produktinfo.conrad.com/datenblaetter/550000-574999/556441-da-01-de-LEITERPLATTENKL__PTSM_0_5__8_2_5_H_THR.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,16+1) rm=5.08 package_height=9.8 leftbottom_offset=[rm/2, 4.6] ddrill=1.3 pad=[2.6,2.6] screw_diameter=3 bevel_height=[0.5,2,6.9] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3.5] nibbleSize=[] nibblePos=[] for p in pins: name="MKDS-1,5-{0}-{1:2.3}".format(p,rm); webpage="http://www.farnell.com/datasheets/100425.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,16+1) rm=5 package_height=9.8 leftbottom_offset=[rm/2, 4.6] ddrill=1.3 pad=[2.6,2.6] screw_diameter=3 bevel_height=[0.5,2,6.9] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3.5] nibbleSize=[] nibblePos=[] for p in pins: name="MKDS-1,5-{0}".format(p); webpage="http://www.farnell.com/datasheets/100425.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,16+1) rm=5.08 package_height=11.2 leftbottom_offset=[rm/2, 5.3] ddrill=1.3 pad=[2.6,2.6] screw_diameter=4 bevel_height=[0.5,3,9.2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3.4] nibbleSize=[] nibblePos=[] for p in pins: name="MKDS-3-{0}-{1:2.3}".format(p,rm); webpage="http://www.farnell.com/datasheets/2138224.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,16+1) rm=3.5 package_height=7.6 leftbottom_offset=[rm/2, package_height-3.1] ddrill=1.2 pad=[2.4,2.4] screw_diameter=3 bevel_height=[0.4,1.5] slit_screw=True screw_pin_offset=[0,0] secondDrillDiameter=0 secondDrillOffset=[0,2.54] secondDrillPad=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,1.7] nibbleSize=[] nibblePos=[] for p in pins: name="PT-1,5-{0}-{1:1.2}-H".format(p,rm); webpage=""; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,16+1) rm=5.0 package_height=9 leftbottom_offset=[rm/2, package_height-4] ddrill=1.3 pad=[2.6,2.6] screw_diameter=4 bevel_height=[0.4,1.5] slit_screw=True screw_pin_offset=[0,0] secondDrillDiameter=0 secondDrillOffset=[0,2.54] secondDrillPad=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.4] nibbleSize=[] nibblePos=[] for p in pins: name="PT-1,5-{0}-{1:1.2}-H".format(p,rm); webpage="http://www.mouser.com/ds/2/324/ItemDetail_1935161-922578.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,3+1) rm=2.54 package_height=6.2 leftbottom_offset=[1.5, 3.1] ddrill=1.1 pad=[2.2,2.2] screw_diameter=2.2 bevel_height=[0.5,5.8] slit_screw=True screw_pin_offset=[0,0] secondDrillDiameter=1.1 secondDrillOffset=[0,2.54] secondDrillPad=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.0] nibbleSize=[] nibblePos=[] for p in pins: name="MPT-0,5-{0}-{1:2.3}".format(p,rm); webpage="http://www.mouser.com/ds/2/324/ItemDetail_1725656-920552.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(4,12+1) rm=2.54 package_height=6.2 leftbottom_offset=[1.5, 3.1] ddrill=1.1 pad=[2.2,2.2] screw_diameter=2.2 bevel_height=[0.5,5.8] slit_screw=True screw_pin_offset=[0,0] secondDrillDiameter=0 secondDrillOffset=[0,2.54] secondDrillPad=[0,0] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,-4] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,2.0] nibbleSize=[] nibblePos=[] for p in pins: name="MPT-0,5-{0}-{1:2.3}".format(p,rm); webpage="http://www.mouser.com/ds/2/324/ItemDetail_1725672-916605.pdf"; classname_description="Terminal Block Phoenix {0}".format(name); footprint_name="TerminalBlock_Phoenix_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/TerminalBlock_RND/make_TerminalBlock_RND.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note="script-generated using https://github.com/pointhi/kicad-footprint-generator/scripts/TerminalBlock_RND"; classname="TerminalBlock_RND" pins=range(2,12+1) rm=5 package_height=10 leftbottom_offset=[rm/2,package_height-2.3] ddrill=1.3 pad=[2.5,2.5] bevel_height=[3.5] opening=[4.1,5.4] opening_yoffset=package_height-1-opening[1] secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[0,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=[0,3] nibbleSize=[] nibblePos=[] for p in pins: makeTerminalBlockVertical(footprint_name="TerminalBlock_RND_205-{0:05}_1x{2:02}_P{1:3.2f}mm_Vertical".format(274+p, rm, p), pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize,nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/TerminalBlock_RND", classname="TerminalBlock_RND", classname_description="terminal block RND 205-{0:05}".format(76+p), webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00276_DB_EN.pdf", script_generated_note=script_generated_note) pins=range(2,12+1) rm=5.08 package_height=10.6 leftbottom_offset=[2.54, 5.3] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[0.6,2.8,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=[2.5,.5] secondHoleOffset=[0,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]] thirdHoleDiameter=0 thirdHoleOffset=[0,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] nibbleSize=[]#[0.6,1.2] nibblePos=[]#[-nibbleSize[0],0.25] fabref_offset=0 for p in pins: name="205-{0:05}".format(285+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00287_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=5 package_height=8.1 leftbottom_offset=[2.5, 4.05] ddrill=1.1 pad=[2.1,2.1] screw_diameter=3 bevel_height=[0.6,1.2,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=[2.5,1] secondHoleOffset=[0,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] thirdHoleDiameter=0 thirdHoleOffset=[rm/2,0] fourthHoleDiameter=0 fourthHoleOffset=[rm/2,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] fabref_offset=0 nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(43+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00045_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=5 package_height=12.6 leftbottom_offset=[rm/2, 6.5] ddrill=1.3 pad=[2.5,2.5] screw_diameter=2.2 bevel_height=[7.7,9.8] vsegment_lines_offset=[] opening=[3.0,5] opening_xoffset=0 opening_yoffset=2 opening_elliptic=False secondDrillDiameter=0 secondDrillOffset=[2.5,-5] secondDrillPad=pad secondHoleDiameter=0 secondHoleOffset=[0,0] thirdHoleDiameter=0 thirdHoleOffset=[1.25,0] fourthHoleDiameter=0 fourthHoleOffset=[1.25,-5.75] fifthHoleDiameter=0 fifthHoleOffset=[1.25,-0.75] secondEllipseSize=[3.2,2.5] secondEllipseOffset=[0,-4.7] fabref_offset=[0,-1] nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(54+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00056_DB_EN.pdf" makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, vsegment_lines_offset=vsegment_lines_offset, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, opening_elliptic=opening_elliptic, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, fifthHoleDiameter=fifthHoleDiameter,fifthHoleOffset=fifthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, secondEllipseSize=secondEllipseSize,secondEllipseOffset=secondEllipseOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=10 package_height=10.3 leftbottom_offset=[rm/4, 5] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[0.6,1.2,package_height-2] slit_screw=False screw_pin_offset=[0,0] secondHoleDiameter=[2.5,1] secondHoleOffset=[0,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] thirdHoleDiameter=screw_diameter thirdHoleOffset=[rm/2,0] fourthHoleDiameter=[2.5,1] fourthHoleOffset=[rm/2,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] fabref_offset=[0,3] nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(76+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00078_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=7.5 package_height=10.3 leftbottom_offset=[rm/2, 5] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[0.6,1.2,package_height-2] slit_screw=False screw_pin_offset=[0,0] secondHoleDiameter=[2.5,1] secondHoleOffset=[0,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] thirdHoleDiameter=0 thirdHoleOffset=[rm/2,0] fourthHoleDiameter=0 fourthHoleOffset=[rm/2,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] fabref_offset=[0,3] nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(65+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00067_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=10 package_height=8.1 leftbottom_offset=[2.5, 4.05] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[0.6,1.2,package_height-2] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=[2.5,1] secondHoleOffset=[0,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] thirdHoleDiameter=screw_diameter thirdHoleOffset=[rm/2,0] fourthHoleDiameter=[2.5,1] fourthHoleOffset=[rm/2,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] fabref_offset=0 nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(296+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00298_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=5.08 package_height=8.45 leftbottom_offset=[2.54, 4.05] ddrill=1.1 pad=[2.1,2.1] screw_diameter=2.5 bevel_height=[0.5,1.6,package_height-1.85] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=[2.5,1] secondHoleOffset=[0,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] thirdHoleDiameter=0 thirdHoleOffset=[0,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] nibbleSize=[]#[0.6,1.2] nibblePos=[]#[-nibbleSize[0],0.25] fabref_offset=0 for p in pins: name="205-{0:05}".format(230+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00232_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=5 package_height=7.6 leftbottom_offset=[2.5, 3.5] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[0.6,1.2,package_height-1.7] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=1.1 secondHoleOffset=[0,-3] thirdHoleDiameter=0 thirdHoleOffset=[0,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] nibbleSize=[]#[0.6,1.2] nibblePos=[]#[-nibbleSize[0],0.25] fabref_offset=0 for p in pins: name="205-{0:05}".format(10+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00012_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=10.16 package_height=8.3 leftbottom_offset=[2.54, 4.55] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[0.6, 1.2, package_height-1.5] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=[2.5,1] secondHoleOffset=[0,-(package_height-leftbottom_offset[1])+secondHoleDiameter[1]/2] thirdHoleDiameter=screw_diameter thirdHoleOffset=[rm/2,0] fourthHoleDiameter=secondHoleDiameter fourthHoleOffset=[rm/2,secondHoleOffset[1]] fabref_offset=0 #[0,2.5] nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(239+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00023_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=5 package_height=9 leftbottom_offset=[2.5, 4] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[1.5] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=1.8 secondHoleOffset=[0,-3] thirdHoleDiameter=0 thirdHoleOffset=[0,0] fourthHoleDiameter=0 fourthHoleOffset=[0,0] fabref_offset=0 #[0,3.8] nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(p-1) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00001_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=range(2,12+1) rm=10 package_height=9 leftbottom_offset=[2.5, 4] ddrill=1.3 pad=[2.5,2.5] screw_diameter=3 bevel_height=[1.5] slit_screw=True screw_pin_offset=[0,0] secondHoleDiameter=1.8 secondHoleOffset=[0,-3] thirdHoleDiameter=screw_diameter thirdHoleOffset=[rm/2,0] fourthHoleDiameter=1.8 fourthHoleOffset=[rm/2,-3] fabref_offset=[0,3.8] nibbleSize=[] nibblePos=[] for p in pins: name="205-{0:05}".format(21+p) footprint_name="TerminalBlock_RND_{0}_1x{2:02}_P{1:3.2f}mm_Horizontal".format(name, rm, p) classname_description="terminal block RND {0}".format(name) webpage="http://cdn-reichelt.de/documents/datenblatt/C151/RND_205-00023_DB_EN.pdf" makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/TerminalBlock_TE-Connectivity/make_TerminalBlock_TE-Connectivity.py ================================================ #!/usr/bin/env python from __future__ import division import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note = ("script-generated using https://github.com" "/pointhi/kicad-footprint-generator/scripts/TerminalBlock_TE-Connectivity") long_classname = "TerminalBlock_TE-Connectivity" classname = "TerminalBlock_TE" pins = range(2,12+1) rm = 2.54 package_height = 6.5 leftbottom_offset = [1.5, 3.25] ddrill = 1.1 pad = [2.1,2.1] screw_diameter = 2.2 bevel_height = [0.4,5.5] slit_screw = True screw_pin_offset = [0,0] secondDrillDiameter = 0 secondDrillOffset = [0,2.54] secondDrillPad = [0,0] secondHoleDiameter = 0 secondHoleOffset = [0,0] thirdHoleDiameter = 0 thirdHoleOffset = [0,-4] fourthHoleDiameter = 0 fourthHoleOffset = [0,0] fabref_offset = [0,2.0] nibbleSize = [] nibblePos = [] for p in pins: name_prefix = "{}-".format(p // 10) if p // 10 > 0 else "" name = "{}282834-{}".format(name_prefix, p % 10) webpage = ("http://www.te.com/commerce/DocumentDelivery/DDEController" "?Action=showdoc&DocId=Customer+Drawing%7F282834%7FC1%7Fpdf" "%7FEnglish%7FENG_CD_282834_C1.pdf") classname_description = "Terminal Block TE {0}".format(name) footprint_name = "{}_{}_1x{:02}_P{:3.2f}mm_Horizontal".format( classname, name, p, rm) makeTerminalBlockStd(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, screw_diameter=screw_diameter, bevel_height=bevel_height, slit_screw=slit_screw, screw_pin_offset=screw_pin_offset, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter, secondDrillOffset=secondDrillOffset, secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name='${KISYS3DMOD}/'+long_classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/TerminalBlock_WAGO/make_TerminalBlock_WAGO.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_terminal_blocks import * if __name__ == '__main__': script_generated_note="script-generated using https://github.com/pointhi/kicad-footprint-generator/scripts/TerminalBlock_WAGO"; classname="TerminalBlock_WAGO" pins=[1,2,3,4,5,6,7,8,9,10,12,16,24] rm=7.5 package_height=15 leftbottom_offset=[2.75, 6.7, 3.75] ddrill=1.2 pad=[2,3] screw_diameter=2.2 bevel_height=[2.9] vsegment_lines_offset=[-1.25] opening=[2.9,2.3] opening_xoffset=1.25 opening_yoffset=1.45 opening_elliptic=True secondDrillDiameter=ddrill secondDrillOffset=[2.5,-5] secondDrillPad=pad secondHoleDiameter=[4,4.4] secondHoleOffset=[1.25,0] thirdHoleDiameter=[4,1] thirdHoleOffset=[1.25,0] fourthHoleDiameter=3#4 fourthHoleOffset=[1.25,-5.75] fifthHoleDiameter=0 fifthHoleOffset=[2.5,-0.75] secondEllipseSize=[0,0] secondEllipseOffset=[1.25,2.5] fabref_offset=[0,-1] nibbleSize=[] nibblePos=[] for p in pins: name="804-{0}".format(300+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, vsegment_lines_offset=vsegment_lines_offset, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, opening_elliptic=opening_elliptic, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, fifthHoleDiameter=fifthHoleDiameter,fifthHoleOffset=fifthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, secondEllipseSize=secondEllipseSize,secondEllipseOffset=secondEllipseOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=[1,2,3,4,5,6,7,8,9,10,12,16,24] rm=5 package_height=15 leftbottom_offset=[2.75, 6.7, 3.75] ddrill=1.2 pad=[2,3] screw_diameter=2.2 bevel_height=[2.9] vsegment_lines_offset=[-1.25] opening=[2.9,2.3] opening_xoffset=1.25 opening_yoffset=1.45 opening_elliptic=True secondDrillDiameter=ddrill secondDrillOffset=[2.5,-5] secondDrillPad=pad secondHoleDiameter=[4,4.4] secondHoleOffset=[1.25,0] thirdHoleDiameter=[4,1] thirdHoleOffset=[1.25,0] fourthHoleDiameter=3#4 fourthHoleOffset=[1.25,-5.75] fifthHoleDiameter=0 fifthHoleOffset=[1.25,-0.75] secondEllipseSize=[0,0] secondEllipseOffset=[1.25,2.5] fabref_offset=[0,-1] nibbleSize=[] nibblePos=[] for p in pins: name="804-{0}".format(100+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, vsegment_lines_offset=vsegment_lines_offset, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, opening_elliptic=opening_elliptic, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, fifthHoleDiameter=fifthHoleDiameter,fifthHoleOffset=fifthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, secondEllipseSize=secondEllipseSize,secondEllipseOffset=secondEllipseOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=[1,2,3,4,6,8,12,16,24,36,48] rm=5 package_height=14 leftbottom_offset=[3.5, 9, 3.8] ddrill=1.15 pad=[1.5,3] screw_diameter=2.2 bevel_height=[1,6.7,9.5] opening=[4,3.3] opening_xoffset=0.5 opening_yoffset=1.3#package_height-leftbottom_offset[1]-opening[1]/2 secondDrillDiameter=ddrill secondDrillOffset=[0,5] secondDrillPad=pad secondHoleDiameter=[5,14] secondHoleOffset=[0.5,2] thirdHoleDiameter=[4,1] thirdHoleOffset=[0.5,3.2] fourthHoleDiameter=[1,2.5] fourthHoleOffset=[0.5,-3.4] fabref_offset=[0,-1] nibbleSize=[] nibblePos=[] for p in pins: name="236-{0}".format(100+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) name="236-{0}".format(400+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=[1,2,3,4,6,8,12,16,24] rm=7.5 package_height=14 leftbottom_offset=[3.5, 9, 6.3] ddrill=1.15 pad=[1.5,3] screw_diameter=2.2 bevel_height=[1,6.7,9.5] opening=[4,3.3] opening_xoffset=0.5 opening_yoffset=1.3#package_height-leftbottom_offset[1]-opening[1]/2 secondDrillDiameter=ddrill secondDrillOffset=[0,5] secondDrillPad=pad secondHoleDiameter=[rm,package_height] secondHoleOffset=[1.75,2] thirdHoleDiameter=[4,1] thirdHoleOffset=[0.5,3.2] fourthHoleDiameter=1,2.5 fourthHoleOffset=[0.5,-3.4] fabref_offset=[0,-1] nibbleSize=[] nibblePos=[] for p in pins: name="236-{0}".format(200+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) name="236-{0}".format(500+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) pins=[1,2,3,4,6,8,12,16,24] rm=10 package_height=14 leftbottom_offset=[3.5, 9, 8.8] ddrill=1.15 pad=[1.5,3] screw_diameter=2.2 bevel_height=[1,6.7,9.5] opening=[4,3.3] opening_xoffset=0.5 opening_yoffset=1.3#package_height-leftbottom_offset[1]-opening[1]/2 secondDrillDiameter=ddrill secondDrillOffset=[0,5] secondDrillPad=pad secondHoleDiameter=[rm,package_height] secondHoleOffset=[3,2] thirdHoleDiameter=[4,1] thirdHoleOffset=[0.5,3.2] fourthHoleDiameter=1,2.5 fourthHoleOffset=[0.5,-3.4] fabref_offset=[0,-1] nibbleSize=[] nibblePos=[] for p in pins: name="236-{0}".format(300+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) name="236-{0}".format(600+p); webpage=""; classname_description="Terminal Block WAGO {0}".format(name); footprint_name="TerminalBlock_WAGO_{0}_1x{2:02}_P{1:3.2f}mm_45Degree".format(name, rm, p) makeTerminalBlock45Degree(footprint_name=footprint_name, pins=p, rm=rm, package_height=package_height, leftbottom_offset=leftbottom_offset, ddrill=ddrill, pad=pad, opening=opening, opening_xoffset=opening_xoffset, opening_yoffset=opening_yoffset, bevel_height=bevel_height, secondHoleDiameter=secondHoleDiameter, secondHoleOffset=secondHoleOffset, thirdHoleDiameter=thirdHoleDiameter, thirdHoleOffset=thirdHoleOffset, fourthHoleDiameter=fourthHoleDiameter, fourthHoleOffset=fourthHoleOffset, secondDrillDiameter=secondDrillDiameter,secondDrillOffset=secondDrillOffset,secondDrillPad=secondDrillPad, nibbleSize=nibbleSize, nibblePos=nibblePos, fabref_offset=fabref_offset, tags_additional=[], lib_name="${KISYS3DMOD}/"+classname, classname=classname, classname_description=classname_description, webpage=webpage, script_generated_note=script_generated_note) ================================================ FILE: scripts/Vigortronix/vigotronix.py ================================================ #!/usr/bin/env python ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' #sizes,shapes,etc] #prefix, serie, Type, W, L, H, PDiam, pin1x, pin1y, pin2x, pin2y, pin3x, pin3y, pin4x, pin4y converters = [ ["ACDC-Conv_Vigortronix", "VTX-214-010-XXX", 0, 56.0, 36.0, 25.5, 1.5, 0, 0, 12, 0, 0, 48, 5, 48 ], ["ACDC-Conv_Vigortronix", "VTX-214-010-XXX_Miniature", 0, 45.5, 30.0, 24.0, 1.5, 0, 0, 12, 0, 12, 39, 5, 39,], ] import sys import os import math output_dir = os.getcwd() #if specified as an argument, extract the target directory for output footprints if len(sys.argv) > 1: out_dir = sys.argv[1] if os.path.isabs(out_dir) and os.path.isdir(out_dir): output_dir = out_dir else: out_dir = os.path.join(os.getcwd(),out_dir) if os.path.isdir(out_dir): output_dir = out_dir if output_dir and not output_dir.endswith(os.sep): output_dir += os.sep #import KicadModTree files sys.path.append("..\\..") from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray for converter in converters: prefix,Serie,Type,W,L,H,PDiam,pin1x, pin1y, pin2x, pin2y, pin3x, pin3y, pin4x, pin4y=converter if Type == 0: desc = "Vigortronix " + Serie + " serie of ACDC converter" tags = "Vigortronix " + Serie + " serie of ACDC converter" TargetDir = "Converters_DCDC_ACDC.3dshapes" Datasheet = "http://www.vigortronix.com/10WattACDCPCBPowerModule.aspx" PadSize = 2.0 * PDiam fp_name = prefix + "_" + Serie fp = Footprint(fp_name) description = desc + ", " + Datasheet x1 = 0 y1 = 0 x2 = 0 y2 = 0 # # Add the component outline # # Top line Layer = ['F.Fab', 'F.SilkS', 'F.CrtYd'] LayerW = [0.1, 0.12, 0.05] LayerD = [0, 0.12, 0.25] for i in range(0, 3): myLayer = Layer[i] myLayerW = LayerW[i] myLayerD = LayerD[i] # # Top line if (i == 0): x1 = 0 - ((L - (pin2x - pin1x)) / 2.0) - myLayerD y1 = 0 - ((W - (pin3y - pin1y)) / 2.0) - myLayerD x2 = -1 y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # x1 = x2; y1 = y2 x2 = 0 y2 = y1 + 1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # x1 = x2; y1 = y2 x2 = 1 y2 = y1 - 1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # x1 = x2; y1 = y2 x2 = L - ((L - (pin2x - pin1x)) / 2.0) + myLayerD y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # else: x1 = 0 - ((L - (pin2x - pin1x)) / 2.0) - myLayerD y1 = 0 - ((W - (pin3y - pin1y)) / 2.0) - myLayerD x2 = L - ((L - (pin2x - pin1x)) / 2.0) + myLayerD y2 = y1 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # # Right Line # x1 = x2 y1 = y2 x2 = x1 y2 = W - ((W - (pin3y - pin1y)) / 2.0) + myLayerD fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # # Bottom Line # x1 = x2 y1 = y2 x2 = 0 - ((L - (pin2x - pin1x)) / 2.0) - myLayerD y2 = y2 fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # # Left Line # x1 = x2 y1 = y2 x2 = 0 - ((L - (pin2x - pin1x)) / 2.0) - myLayerD y2 = 0 - ((W - (pin3y - pin1y)) / 2.0) - myLayerD fp.append(Line(start=[round(x1, 2), round(y1, 2)],end=[round(x2, 2), round(y2, 2)],layer=myLayer,width=myLayerW)) # # # Add holes # if (i == 0): fp.append(Pad(number=1,at=[pin1x, pin1y], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_RECT, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam, 2))) fp.append(Pad(number=2,at=[pin2x, pin2y], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam, 2))) fp.append(Pad(number=3,at=[pin3x, pin3y], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam, 2))) fp.append(Pad(number=4,at=[pin4x, pin4y], layers=Pad.LAYERS_THT, shape=Pad.SHAPE_CIRCLE, type=Pad.TYPE_THT, size=[PadSize,PadSize], drill=round(PDiam, 2))) fp.setTags(tags) fp.setDescription(description) # # Set general values # cx = 0 - ((L - (pin2x - pin1x)) / 2.0) + 2 cy = 0 - ((W - (pin3y - pin1y)) / 2.0) - 1.5 fp.append(Text(type='reference', text='REF**', at=[round(cx, 2), round(cy, 2)], layer='F.SilkS')) # cx = (pin2x - pin1x) / 2.0 cy = ((pin3y - pin1y)) - ((L - (pin3y - pin1y)) / 2.0) fp.append(Text(type='value', text=fp_name, at=[round(cx, 2), round(cy, 2)], layer='F.Fab')) # cx = (L / 2.0) + (0 - ((L - (pin2x - pin1x)) / 2.0) - myLayerD) cy = (pin3y - pin1y) / 2.0 fp.append(Text(type='user', text="%R", at=[round(cx, 2), round(cy, 2)], layer='F.Fab')) # # Add 3D model # fp.append(Model(filename="${KISYS3DMOD}/" + TargetDir + "/" + fp_name + ".wrl", at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) #filename filename = output_dir + fp_name + ".kicad_mod" file_handler = KicadFileHandler(fp) file_handler.writeFile(filename) ================================================ FILE: scripts/example_kicadmodtree_script.py ================================================ #!/usr/bin/env python ''' kicad-footprint-generator 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. kicad-footprint-generator 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. ''' import sys import os sys.path.append(os.path.join(sys.path[0],"..")) #sys.path.append('../..') # enable package import from parent directory from KicadModTree import * from KicadModTree.nodes.specialized.PadArray import PadArray if __name__ == '__main__': footprint_name = "example_footprint" # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription("A example footprint") kicad_mod.setTags("example") # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[0,-3], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[1.5,3], layer='F.Fab')) # create silscreen kicad_mod.append(RectLine(start=[-2,-2], end=[5,2], layer='F.SilkS', width=0.15)) # create courtyard kicad_mod.append(RectLine(start=[-2.25,-2.25], end=[5.25,2.25], layer='F.CrtYd', width=0.05, offset=2)) # create pads kicad_mod.append(Pad(number=7, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0,0], size=[2,2], drill=1.2, layers=['*.Cu', '*.Mask', 'F.SilkS'])) kicad_mod.append(Pad(number=22, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[3,0], size=[2,2], drill=1.2, layers=['*.Cu', '*.Mask', 'F.SilkS'])) kicad_mod.append(Pad(number=12, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[3,0], size=[2,2], drill=1.2, layers=['*.Cu', '*.Mask', 'F.SilkS'])) # add model kicad_mod.append(Model(filename="example.3dshapes/example_footprint.wrl" ,at=[0,0,0] ,scale=[1,1,1] ,rotate=[0,0,0])) kicad_mod.append(PadArray(pincount=10,spacing=[1,-1],center=[0,0], initial=5, increment=2, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, size=[1,2], layers=["*.Cu"])) # output kicad model #print(kicad_mod) # print render tree #print(kicad_mod.getRenderTree()) #print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('example_footprint.kicad_mod') ================================================ FILE: scripts/general/StandardBox.py ================================================ # KicadModTree 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. # # KicadModTree 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 kicad-footprint-generator. If not, see < http://www.gnu.org/licenses/ >. # # (C) 2016 by Thomas Pointhuber, # # This module Create a standard box in various layers including a pin 1 marker tap or chamfer # from KicadModTree import * from KicadModTree.Point import * from KicadModTree.PolygonPoints import * from KicadModTree.nodes.Node import Node from KicadModTree.nodes.base.Line import Line from KicadModTree.nodes.base.Text import Text class koaLine: def __init__(self, sx, sy, ex, ey, layer, width): self.sx = sx self.sy = sy self.ex = ex self.ey = ey self.k = 0.0 self.m = 0.0 self.l = 0.0 self.IsVertical = False self.layer = layer self.width = width if ex != sx: self.k = (ey - sy) / (ex - sx) self.m = sy - (self.k * sx) else: self.IsVertical = True # # Get the line lenght # x1 = min(self.sx, self.ex) x2 = max(self.sx, self.ex) y1 = min(self.sy, self.ey) y2 = max(self.sy, self.ey) x1 = x2 - x1 y1 = y2 - y1 self.l = sqrt((x1 * x1) + (y1 * y1)) class StandardBox(Node): r"""Add a Polygone Line to the render tree :param \**kwargs: See below :Keyword Arguments: * *footprint* (``list(Point)``) -- The foot print * *description* (``str``) -- The description * *datasheet* (``str``) -- The url to the data sheet * *at* (``Point``) -- Where is upper left corner, in cartesian cordinate system (minus y below x axis) * *size* (``Point``) -- The width and height of the rectangle * *tags* (``str``) -- A foot prints tag attribute * *SmdTht* (``str``) -- A foot prints tht/smd attribute * *extratexts* (``list(x, y, 'text', layer, sizex, sizey)``) -- A list of extra txts to be placed on the footprint * *pins* (``list(type, number, x, y, sizex, sizey, drill)``) -- List of tht/smd/npth holes * *file3Dname* (``str``) -- The path to the 3D model name :Example: # # pycodestyle complain over long lines so the complete on is placed in a comment instead # # StandardBox(footprint=f, description=description, datasheet=datasheet, at=at, size=size, tags=fptag, SmdTht=SmdTht, # extratexts=extratexts, pins=pins, file3Dname = "${KISYS3DMOD}/" + dir3D + "/" + footprint_name + ".wrl"))) # >>> from KicadModTree import * >>> StandardBox(footprint=f, description=description, ....) """ def __init__(self, **kwargs): Node.__init__(self) # self.virtual_childs = [] # self._initPosition(**kwargs) self._initSize(**kwargs) self._initFootPrint(**kwargs) # # # self._initDesriptionNode(**kwargs) self._initTagNode(**kwargs) self._initAttributeNode(**kwargs) self._initFile3DNameNode(**kwargs) self._initExtraTextNode(**kwargs) self.extraffablines = kwargs.get('extraffablines') self.typeOfBox = str(kwargs.get('typeOfBox')) self.pins = kwargs.get('pins') # # Create foot print parts # # self._createPinsNode() self._createFFabLine() self._createPin1MarkerLine() self._createFSilkSLine() self._createFCrtYdLine() # def getVirtualChilds(self): # # return self.virtual_childs def _initPosition(self, **kwargs): if not kwargs.get('at'): raise KeyError('Upper left position not declared (like "at: [0,0]")') self.at = Point2D(kwargs.get('at')) self.at.y = 0.0 - self.at.y def _initSize(self, **kwargs): if not kwargs.get('size'): raise KeyError('Size not declared (like "size: [1,1]")') if type(kwargs.get('size')) in [int, float]: # when the attribute is a simple number, use it for x and y self.size = Point2D([kwargs.get('size'), kwargs.get('size')]) else: size_original = kwargs.get('size') self.corners = [] if len(size_original ) > 2: self.corners = size_original[2:] self.size = Point2D(size_original[0], size_original[1]) def _initFootPrint(self, **kwargs): if not kwargs.get('footprint'): raise KeyError('footprint node is missing') self.footprint = kwargs.get('footprint') # self.footprint_name = self.footprint.name # self.FFabWidth = 0.10 self.FSilkSWidth = 0.12 self.FCrtYdWidth = 0.05 # self.p1m = 3.0 self.REF_P_w = 1.0 self.REF_P_h = 1.0 # if self.size.x < 8.0 or self.size.y < 8.0: dd = self.size.y / 3.0 if self.size.x < self.size.y: dd = self.size.x / 3.0 self.p1m = dd if dd < self.REF_P_w: self.REF_P_w = dd self.REF_P_h = self.REF_P_w new_node = Text(type='user', text='%R', at=[self.at.x + (self.size.x / 2.0), self.at.y + (self.size.y / 2.0)], layer='F.Fab', size=[self.REF_P_w, self.REF_P_h]) new_node._parent = self self.virtual_childs.append(new_node) # # new_node = Text(type='reference', text='REF**', at=[self.at.x + 2.5, self.at.y - 1.2], layer='F.SilkS') new_node._parent = self self.virtual_childs.append(new_node) # # new_node = Text(type="value", text=self.footprint_name, at=[self.at.x + (self.size.x / 2.0), self.at.y + self.size.y + 1.0], layer="F.Fab") new_node._parent = self self.virtual_childs.append(new_node) def _initDesriptionNode(self, **kwargs): if not kwargs.get('description'): raise KeyError('Description not declared (like description: "Bul Holder )') if not kwargs.get('datasheet'): raise KeyError('datasheet not declared (like datasheet: http://www.bulgin.com/media/bulgin/data/Battery_holders.pdf)') self.description = str(kwargs.get('description')) + " (Script generated with StandardBox.py) (" + str(kwargs.get('datasheet')) + ")" self.footprint.setDescription(self.description) def _initTagNode(self, **kwargs): if not kwargs.get('tags'): raise KeyError('tags not declared (like "tags: "Bulgin Battery Holder, BX0033, Battery Type 1xPP3")') self.tags = str(kwargs.get('tags')) self.footprint.setTags(self.tags) def _initAttributeNode(self, **kwargs): if kwargs.get('SmdTht'): self.SmdTht = str(kwargs.get('SmdTht')) if self.SmdTht == "smd": self.footprint.setAttribute("smd") def _initFile3DNameNode(self, **kwargs): if not kwargs.get('file3Dname'): raise KeyError('file3Dname not declared') self.file3Dname = str(kwargs.get('file3Dname')) self.footprint.append(Model(filename=self.file3Dname, at=[0.0, 0.0, 0.0], scale=[1.0, 1.0, 1.0], rotate=[0.0, 0.0, 0.0])) def _initExtraTextNode(self, **kwargs): if kwargs.get('extratexts'): self.extratexts = kwargs.get('extratexts') # for n in self.extratexts: at = [n[0], 0.0-n[1]] stss = n[2] new_node = Text(type="user", text=stss, at=at) # if len(n) > 3: new_node.layer = n[3] if len(n) > 5: new_node.size = Point2D([n[4], n[5]]) new_node._parent = self self.virtual_childs.append(new_node) def _createFFabLine(self): ffabline = [] self.boxffabline = [] # # x = self.at.x y = self.at.y w = self.size.x h = self.size.y self.boxffabline.append(koaLine(x, y, x + w, y, 'F.Fab', self.FFabWidth)) self.boxffabline.append(koaLine(x + w, y, x + w, y + h, 'F.Fab', self.FFabWidth)) self.boxffabline.append(koaLine(x + w, y + h, x, y + h, 'F.Fab', self.FFabWidth)) self.boxffabline.append(koaLine(x, y + h, x, y, 'F.Fab', self.FFabWidth)) # # Add a chamfer # dd = w * 0.25 if dd > 1.0: dd = 1.0 if w < 2.0: dd = w / 3.0 if h < 2.0: dd = h / 3.0 # # x0 = x + dd y0 = y x9 = x0 y9 = y0 # x1 = x + w y1 = y x2 = x1 y2 = y1 # x3 = x + w y3 = y + h x4 = x3 y4 = y3 # x5 = x y5 = y + h x6 = x5 y6 = y5 # x7 = x y7 = y + dd x8 = x7 y8 = y7 # # for nn in self.corners: if nn[0] == 'ULP': x0 = x + nn[1] x9 = x0 y8 = y + nn[2] y9 = y8 y7 = y8 new_node = Line(start=Point2D(x9, y9), end=Point2D(x0, y0), layer='F.Fab', width=self.FFabWidth) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'ULR': x0 = x + nn[1] y7 = y + nn[1] x8 = x7 x9 = x7 y8 = y7 y9 = y7 new_node = Arc(center=Point2D(x0, y7), start=Point2D(x7, y7), layer='F.Fab', width=self.FFabWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'URP': x1 = (x + w) - nn[1] y2 = y + nn[2] new_node = Line(start=Point2D(x1, y1), end=Point2D(x1, y2), layer='F.Fab', width=self.FFabWidth) new_node._parent = self self.virtual_childs.append(new_node) # new_node = Line(start=Point2D(x1, y2), end=Point2D(x2, y2), layer='F.Fab', width=self.FFabWidth) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'URR': x1 = (x + w) - nn[1] y2 = y + nn[1] new_node = Arc(center=Point2D(x1, y2), start=Point2D(x1, y1), layer='F.Fab', width=self.FFabWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'LRP': x4 = (x + w) - nn[1] y3 = (y + h) - nn[1] new_node = Line(start=Point2D(x3, y3), end=Point2D(x4, y3), layer='F.Fab', width=self.FFabWidth) new_node._parent = self self.virtual_childs.append(new_node) # new_node = Line(start=Point2D(x4, y3), end=Point2D(x4, y4), layer='F.Fab', width=self.FFabWidth) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'LRR': x4 = (x + w) - nn[1] y3 = (y + h) - nn[1] new_node = Arc(center=Point2D(x4, y3), start=Point2D(x3, y3), layer='F.Fab', width=self.FFabWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'LLR': x5 = x + nn[1] y6 = (y + h) - nn[1] new_node = Arc(center=Point2D(x5, y6), start=Point2D(x5, y5), layer='F.Fab', width=self.FFabWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'LLP': x5 = x + nn[1] y6 = (y + h) - nn[2] new_node = Line(start=Point2D(x5, y5), end=Point2D(x5, y6), layer='F.Fab', width=self.FFabWidth) new_node._parent = self self.virtual_childs.append(new_node) # new_node = Line(start=Point2D(x5, y6), end=Point2D(x6, y6), layer='F.Fab', width=self.FFabWidth) new_node._parent = self self.virtual_childs.append(new_node) ffabline.append(koaLine(x0, y0, x1, y1, 'F.Fab', self.FFabWidth)) ffabline.append(koaLine(x2, y2, x3, y3, 'F.Fab', self.FFabWidth)) ffabline.append(koaLine(x4, y4, x5, y5, 'F.Fab', self.FFabWidth)) ffabline.append(koaLine(x6, y6, x7, y7, 'F.Fab', self.FFabWidth)) ffabline.append(koaLine(x8, y8, x9, y9, 'F.Fab', self.FFabWidth)) # # for n in ffabline: new_node = Line(start=Point2D(round(n.sx, 2), round(n.sy, 2)), end=Point2D(round(n.ex, 2), round(n.ey, 2)), layer=n.layer, width=n.width) if n.width < 0.0: new_node = Line(start=Point2D(round(n.sx, 2), round(n.sy, 2)), end=Point2D(round(n.ex, 2), round(n.ey, 2)), layer=n.layer) new_node._parent = self self.virtual_childs.append(new_node) def _createPin1MarkerLine(self): # # Add pin 1 marker line # x1 = self.at.x - 0.5 y1 = self.at.y - 0.5 # new_node = Line(start=Point2D(round(x1, 2), round(y1 + self.p1m, 2)), end=Point2D(round(x1, 2), round(y1, 2)), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) # new_node = Line(start=Point2D(round(x1, 2), round(y1, 2)), end=Point2D(round(x1 + self.p1m, 2), round(y1, 2)), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) def _createFSilkSLine(self): self.fsilksline = [] # # # # Check all holes and pads, if a pad or hole is on the silk line # then jump over the pad/hole # for n in self.boxffabline: x1 = min(n.sx, n.ex) y1 = min(n.sy, n.ey) x2 = max(n.sx, n.ex) y2 = max(n.sy, n.ey) # # if (x1 < 0.0 and y1 < 0.0 and y2 < 0.0) or (x1 < 0.0 and y1 > 0.0 and y2 > 0.0): # # Top and bottom line # x1_t = x1 - 0.12 x2_t = x2 + 0.12 x3_t = x1_t x4_t = x2_t # if y1 < 0.0: # Top line y1_t = y1 - 0.12 y2_t = y2 - 0.12 y3_t = y1_t y4_t = y2_t # for nn in self.corners: if nn[0] == 'URR': x2_t = x2_t - (nn[1] + 0.12) if nn[0] == 'ULR': x1_t = x1_t + (nn[1] + 0.12) if nn[0] == 'ULP': x3_t = x1_t x1_t = x1_t + (nn[1]) y3_t = y1_t + (nn[2]) if nn[0] == 'URP': x4_t = x2_t x2_t = x2_t - (nn[1]) y4_t = y1_t + (nn[2]) else: # Bottom line y1_t = y1 + 0.12 y2_t = y2 + 0.12 y3_t = y1_t y4_t = y2_t # for nn in self.corners: if nn[0] == 'LRR': x2_t = x2_t - (nn[1] + 0.12) if nn[0] == 'LLR': x1_t = x1_t + (nn[1] + 0.12) if nn[0] == 'LLP': x3_t = x1_t x1_t = x1_t + (nn[1]) y3_t = y1_t - (nn[2]) if nn[0] == 'LRP': x4_t = x2_t x2_t = x2_t - (nn[1]) y4_t = y1_t - (nn[2]) # EndLine = True foundPad = False UseCorner = True while EndLine: px1 = 10000000.0 px2 = 10000000.0 foundPad = False for n in self.pad: n_min_x = n.at.x - (n.size.x / 2.0) n_min_y = n.at.y - (n.size.y / 2.0) n_max_x = n_min_x + n.size.x n_max_y = n_min_y + n.size.y dd = max(0.25, n.solder_mask_margin) if (n_min_y - 0.25) <= y1_t and (n_max_y + 0.25) > y1_t and n_max_x > x1_t and n_min_x < x2_t: # # This pad is in SilkS line's path # if n_min_x < px1: px1 = n_min_x px2 = n_max_x foundPad = True if foundPad: # # Found at least one pad that is in SilkS's line # if (px1 - 0.25) > x1_t: # # It does not cover the start point # self.fsilksline.append(koaLine(x1_t, y1_t, px1 - 0.25, y2_t, 'F.SilkS', self.FSilkSWidth)) x1_t = px2 + 0.25 else: # # No pads was in the way # if y1 < 0.0 and UseCorner: # Top line for nn in self.corners: if nn[0] == 'ULR': urcdy0 = y1_t + (nn[1] + 0.12) urcdx1 = x1_t - (nn[1] + 0.12) new_node = Arc(center=Point2D(x1_t, urcdy0), start=Point2D(urcdx1, urcdy0), layer='F.SilkS', width=self.FSilkSWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'ULP': new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x1_t, y1_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x3_t, y3_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) # if nn[0] == 'URP': urcdy0 = y4_t + (nn[2]) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x2_t, y2_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x4_t, y4_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) if y1 > 0.0 and UseCorner: # Bottom line for nn in self.corners: if nn[0] == 'LLR': urcdy0 = y1_t - (nn[1] + 0.12) new_node = Arc(center=Point2D(x1_t, urcdy0), start=Point2D(x1_t, y1_t), layer='F.SilkS', width=self.FSilkSWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'LLP': new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x1_t, y1_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x3_t, y3_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) # if nn[0] == 'LRP': urcdy0 = y4_t + (nn[2]) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x2_t, y2_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x4_t, y4_t), layer='F.SilkS', width=self.FSilkSWidth) new_node._parent = self self.virtual_childs.append(new_node) # self.fsilksline.append(koaLine(x1_t, y1_t, x2_t, y2_t, 'F.SilkS', self.FSilkSWidth)) EndLine = False if x1_t >= x2: EndLine = False UseCorner = False if not foundPad and y1 < 0: # for nn in self.corners: if nn[0] == 'URR': urcdy1 = y1_t + (nn[1] + 0.12) new_node = Arc(center=Point2D(x2_t, urcdy1), start=Point2D(x2_t, y2_t), layer='F.SilkS', width=self.FSilkSWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if not foundPad and y1 > 0: # for nn in self.corners: if nn[0] == 'LRR': urcdx1 = x2_t + (nn[1] + 0.12) urcdy1 = y2_t - (nn[1] + 0.12) new_node = Arc(center=Point2D(x2_t, urcdy1), start=Point2D(urcdx1, urcdy1), layer='F.SilkS', width=self.FSilkSWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if (x1 < 0.0 and y1 < 0.0 and y2 > 0.0) or (x1 > 0.0 and y1 < 0.0 and y2 > 0.0): # # Left and right line # y1_t = y1 - 0.12 y2_t = y2 + 0.12 # if x1 < 0.0: # Left line x1_t = min(x1 - 0.12, x2 - 0.12) x2_t = max(x1 - 0.12, x2 - 0.12) for nn in self.corners: if nn[0] == 'ULR': y1_t = y1_t + (nn[1] + 0.12) if nn[0] == 'LLR': y2_t = y2_t - (nn[1] + 0.12) if nn[0] == 'ULP': y1_t = y1_t + (nn[2]) if nn[0] == 'LLP': y2_t = y2_t - (nn[2]) else: # Right line x1_t = min(x1 + 0.12, x2 + 0.12) x2_t = max(x1 + 0.12, x2 + 0.12) # for nn in self.corners: if nn[0] == 'URR': y1_t = y1_t + (nn[1] + 0.12) if nn[0] == 'LRR': y2_t = y2_t - (nn[1] + 0.12) if nn[0] == 'URP': y1_t = y1_t + (nn[2]) if nn[0] == 'LRP': y2_t = y2_t - (nn[2]) # EndLine = True while EndLine: py1 = 10000000.0 py2 = 10000000.0 foundPad = False for n in self.pad: n_min_x = n.at.x - (n.size.x / 2.0) n_min_y = n.at.y - (n.size.y / 2.0) n_max_x = n_min_x + n.size.x n_max_y = n_min_y + n.size.y dd = max(0.25, n.solder_mask_margin) if (n_min_x <= x1_t) and (n_max_x > x1_t) and n_max_y > y1_t and n_min_y < y2_t: # # This pad is in SilkS line's path # if n_min_y < py1: py1 = n_min_y py2 = n_max_y foundPad = True if foundPad: # # Found at least one pad that is in SilkS's line # if (py1 - dd) > y1_t: # # It does not cover the start point # self.fsilksline.append(koaLine(x1_t, y1_t, x2_t, py1 - dd, 'F.SilkS', self.FSilkSWidth)) y1_t = py2 + dd else: # # No pads was in the way # self.fsilksline.append(koaLine(x1_t, y1_t, x2_t, y2_t, 'F.SilkS', self.FSilkSWidth)) EndLine = False if y1_t >= y2: EndLine = False # # for n in self.fsilksline: new_node = Line(start=Point2D(round(n.sx, 2), round(n.sy, 2)), end=Point2D(round(n.ex, 2), round(n.ey, 2)), layer=n.layer, width=n.width) if n.width < 0.0: new_node = Line(start=Point2D(round(n.sx, 2), round(n.sy, 2)), end=Point2D(round(n.ex, 2), round(n.ey, 2)), layer=n.layer) new_node._parent = self self.virtual_childs.append(new_node) def _createFCrtYdLine(self): self.fcrtydline = [] # # # # Check all holes and pads, if a pad or hole is on the crtyrd line # then jump over the pad/hole # for n in self.boxffabline: x1 = min(n.sx, n.ex) y1 = min(n.sy, n.ey) x2 = max(n.sx, n.ex) y2 = max(n.sy, n.ey) # # if (x1 < 0.0 and y1 < 0.0 and y2 < 0.0) or (x1 < 0.0 and y1 > 0.0 and y2 > 0.0): # # Top and bottom line # x1_t = x1 - 0.25 x2_t = x2 + 0.25 x3_t = x1_t x4_t = x2_t # if y1 < 0.0: # Top line y1_t = y1 - 0.25 y2_t = y2 - 0.25 y3_t = y1_t y4_t = y2_t # for nn in self.corners: if nn[0] == 'URR': x2_t = x2_t - (nn[1] + 0.25) if nn[0] == 'ULR': x1_t = x1_t + (nn[1] + 0.25) if nn[0] == 'ULP': x3_t = x1_t x1_t = x1_t + (nn[1]) y3_t = y1_t + (nn[2]) if nn[0] == 'URP': x4_t = x2_t x2_t = x2_t - (nn[1]) y4_t = y1_t + (nn[2]) else: # Bottom line y1_t = y1 + 0.25 y2_t = y2 + 0.25 y3_t = y1_t y4_t = y2_t # for nn in self.corners: if nn[0] == 'LRR': x2_t = x2_t - (nn[1] + 0.25) if nn[0] == 'LLR': x1_t = x1_t + (nn[1] + 0.25) if nn[0] == 'LLP': x3_t = x1_t x1_t = x1_t + (nn[1]) y3_t = y1_t - (nn[2]) if nn[0] == 'LRP': x4_t = x2_t x2_t = x2_t - (nn[1]) y4_t = y1_t - (nn[2]) # EndLine = True UseCorner = True while EndLine: px1 = 10000000.0 py1 = 10000000.0 px2 = 10000000.0 py2 = 10000000.0 foundPad = False for n in self.pad: n_min_x = n.at.x - (n.size.x / 2.0) n_min_y = n.at.y - (n.size.y / 2.0) n_max_x = n_min_x + n.size.x n_max_y = n_min_y + n.size.y dd = max(0.25, n.solder_mask_margin) if (n_min_y - dd) <= y1_t and (n_max_y + dd) > y1_t and n_max_x > x1_t and n_min_x < x2_t: # # This pad is in CrtYd line's path # if n_min_x < px1: px1 = n_min_x py1 = n_min_y px2 = n_max_x py2 = n_max_y foundPad = True if foundPad: # # Found at least one pad that is in CrtYd's line # if (px1 - dd) > x1_t: # # It does not cover the start point # self.fcrtydline.append(koaLine(x1_t, y1_t, px1 - dd, y2_t, 'F.CrtYd', self.FCrtYdWidth)) if y1 < 0.0: # Top line self.fcrtydline.append(koaLine(px1 - dd, y2_t, px1 - dd, py1 - dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px1 - dd, py1 - dd, px2 + dd, py1 - dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px2 + dd, py1 - dd, px2 + dd, y2_t, 'F.CrtYd', self.FCrtYdWidth)) else: # Bottom line self.fcrtydline.append(koaLine(px1 - dd, y2_t, px1 - dd, py2 + dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px1 - dd, py2 + dd, px2 + dd, py2 + dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px2 + dd, py2 + dd, px2 + dd, y2_t, 'F.CrtYd', self.FCrtYdWidth)) x1_t = px2 + dd else: # # No pads was in the way # # # No pads was in the way # if y1 < 0.0 and UseCorner: # Top line for nn in self.corners: if nn[0] == 'ULR': urcdy0 = y1_t + (nn[1] + 0.25) urcdx1 = x1_t - (nn[1] + 0.25) new_node = Arc(center=Point2D(x1_t, urcdy0), start=Point2D(urcdx1, urcdy0), layer='F.CrtYd', width=self.FCrtYdWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'ULP': new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x1_t, y1_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x3_t, y3_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) # if nn[0] == 'URP': urcdy0 = y4_t + (nn[2]) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x2_t, y2_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x4_t, y4_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) if y1 > 0.0 and UseCorner: # Bottom line for nn in self.corners: if nn[0] == 'LLR': urcdy0 = y1_t - (nn[1] + 0.25) new_node = Arc(center=Point2D(x1_t, urcdy0), start=Point2D(x1_t, y1_t), layer='F.CrtYd', width=self.FCrtYdWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if nn[0] == 'LLP': new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x1_t, y1_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x1_t, y3_t), end=Point2D(x3_t, y3_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) # if nn[0] == 'LRP': urcdy0 = y4_t + (nn[2]) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x2_t, y2_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) new_node = Line(start=Point2D(x2_t, y4_t), end=Point2D(x4_t, y4_t), layer='F.CrtYd', width=self.FCrtYdWidth) new_node._parent = self self.virtual_childs.append(new_node) # self.fcrtydline.append(koaLine(x1_t, y1_t, x2_t, y2_t, 'F.CrtYd', self.FCrtYdWidth)) EndLine = False UseCorner = False if x1_t >= x2: EndLine = False if not foundPad and y1 < 0: # for nn in self.corners: if nn[0] == 'URR': urcdy1 = y1_t + (nn[1] + 0.25) new_node = Arc(center=Point2D(x2_t, urcdy1), start=Point2D(x2_t, y2_t), layer='F.CrtYd', width=self.FCrtYdWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if not foundPad and y1 > 0: # for nn in self.corners: if nn[0] == 'LRR': urcdx1 = x2_t + (nn[1] + 0.25) urcdy1 = y2_t - (nn[1] + 0.25) new_node = Arc(center=Point2D(x2_t, urcdy1), start=Point2D(urcdx1, urcdy1), layer='F.CrtYd', width=self.FCrtYdWidth, angle=90.0) new_node._parent = self self.virtual_childs.append(new_node) if (x1 < 0.0 and y1 < 0.0 and y2 > 0.0) or (x1 > 0.0 and y1 < 0.0 and y2 > 0.0): # # Left and right line # y1_t = y1 - 0.25 y2_t = y2 + 0.25 # if x1 < 0.0: # Left line x1_t = x1 - 0.25 x2_t = x1 - 0.25 # for nn in self.corners: if nn[0] == 'ULR': y1_t = y1_t + (nn[1] + 0.25) if nn[0] == 'LLR': y2_t = y2_t - (nn[1] + 0.25) if nn[0] == 'ULP': y1_t = y1_t + (nn[2]) if nn[0] == 'LLP': y2_t = y2_t - (nn[2]) else: # Right line x1_t = x1 + 0.25 x2_t = x2 + 0.25 # for nn in self.corners: if nn[0] == 'URR': y1_t = y1_t + (nn[1] + 0.25) if nn[0] == 'LRR': y2_t = y2_t - (nn[1] + 0.25) if nn[0] == 'URP': y1_t = y1_t + (nn[2]) if nn[0] == 'LRP': y2_t = y2_t - (nn[2]) # EndLine = True while EndLine: px1 = 10000000.0 py1 = 10000000.0 px2 = 10000000.0 py2 = 10000000.0 foundPad = False for n in self.pad: n_min_x = n.at.x - (n.size.x / 2.0) n_min_y = n.at.y - (n.size.y / 2.0) n_max_x = n_min_x + n.size.x n_max_y = n_min_y + n.size.y dd = max(0.26, n.solder_mask_margin) if (n_min_x <= x1_t) and (n_max_x >= x1_t) and n_max_y >= y1_t and n_min_y <= y2_t: # # This pad is in CrtYd line's path # if n_min_y < py1: px1 = n_min_x py1 = n_min_y px2 = n_max_x py2 = n_max_y foundPad = True if foundPad: # # Found at least one pad that is in CrtYd's line # if (py1 - dd) > y1_t: # # It does not cover the start point # self.fcrtydline.append(koaLine(x1_t, y1_t, x2_t, py1 - dd, 'F.CrtYd', self.FCrtYdWidth)) if x1 < 0.0: # Left line self.fcrtydline.append(koaLine(x2_t, py1 - dd, px1 - dd, py1 - dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px1 - dd, py1 - dd, px1 - dd, py2 + dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px1 - dd, py2 + dd, x2_t, py2 + dd, 'F.CrtYd', self.FCrtYdWidth)) else: # Right line self.fcrtydline.append(koaLine(x2_t, py1 - dd, px2 + dd, py1 - dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px2 + dd, py1 - dd, px2 + dd, py2 + dd, 'F.CrtYd', self.FCrtYdWidth)) self.fcrtydline.append(koaLine(px2 + dd, py2 + dd, x2_t, py2 + dd, 'F.CrtYd', self.FCrtYdWidth)) y1_t = py2 + dd else: # # No pads was in the way # self.fcrtydline.append(koaLine(x1_t, y1_t, x2_t, y2_t, 'F.CrtYd', self.FCrtYdWidth)) EndLine = False if y1_t >= y2: EndLine = False # # for n in self.fcrtydline: new_node = Line(start=Point2D(round(n.sx, 2), round(n.sy, 2)), end=Point2D(round(n.ex, 2), round(n.ey, 2)), layer=n.layer, width=n.width) if n.width < 0.0: new_node = Line(start=Point2D(round(n.sx, 2), round(n.sy, 2)), end=Point2D(round(n.ex, 2), round(n.ey, 2)), layer=n.layer) new_node._parent = self self.virtual_childs.append(new_node) def calculateBoundingBox(self): min_x = self.at.x min_y = self.at.y max_x = min_x + self.size.x max_y = min_y + self.size.y for child in self.virtual_childs(): child_outline = child.calculateBoundingBox() min_x = min([min_x, child_outline['min']['x']]) min_y = min([min_y, child_outline['min']['y']]) max_x = max([max_x, child_outline['max']['x']]) max_y = max([max_y, child_outline['max']['y']]) return {'min': Point2D(min_x, min_y), 'max': Point2D(max_x, max_y)} def _createPinsNode(self): # # Add pin and holes # self.pad = [] c = 1 for n in self.pins: c = n[1] x = n[2] y = n[3] sx = n[4] sy = n[5] dh = n[6] if n[0] == 'tht': if c == '1': new_pad = Pad(number=c, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[x, 0.0 - y], size=[sx, sy], drill=dh, layers=Pad.LAYERS_THT) self.footprint.append(new_pad) self.pad.append(new_pad) else: new_pad = Pad(number=c, type=Pad.TYPE_THT, shape=Pad.SHAPE_CIRCLE, at=[x, 0.0 - y], size=[sx, sy], drill=dh, layers=Pad.LAYERS_THT) self.footprint.append(new_pad) self.pad.append(new_pad) if n[0] == 'thtr': if c == '1': new_pad = Pad(number=c, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[x, 0.0 - y], size=[sx, sy], drill=dh, layers=Pad.LAYERS_THT) self.footprint.append(new_pad) self.pad.append(new_pad) else: new_pad = Pad(number=c, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[x, 0.0 - y], size=[sx, sy], drill=dh, layers=Pad.LAYERS_THT) self.footprint.append(new_pad) self.pad.append(new_pad) elif n[0] == 'smd': new_pad = Pad(number=c, type=Pad.TYPE_SMT, shape=Pad.SHAPE_ROUNDRECT, radius_ratio=0.25, at=[x, 0.0 - y], size=[sx, sy], drill=dh, layers=Pad.LAYERS_SMT) self.footprint.append(new_pad) self.pad.append(new_pad) elif n[0] == 'npth': if sy == 0: new_pad = Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_CIRCLE, at=[x, 0.0 - y], size=[sx, sx], drill=dh, layers=Pad.LAYERS_NPTH) self.footprint.append(new_pad) self.pad.append(new_pad) else: new_pad = Pad(type=Pad.TYPE_NPTH, shape=Pad.SHAPE_RECT, at=[x, 0.0 - y], size=[sx, sy], drill=dh, layers=Pad.LAYERS_NPTH) self.footprint.append(new_pad) self.pad.append(new_pad) # ================================================ FILE: scripts/general/new more powerfull generator found under SMD_chip_package_rlc-etc ================================================ ================================================ FILE: scripts/general/smd_chip.py ================================================ #!/usr/bin/env python import sys import os sys.path.append(os.path.join(sys.path[0], "..", "..")) # load parent path of KicadModTree from KicadModTree import * # NOQA from KicadModTree.nodes.base.Pad import Pad # NOQA def smd_chip(args): # init kicad footprint kicad_mod = Footprint(args['name']) kicad_mod.setDescription(args['description']) kicad_mod.setTags(args['tags']) kicad_mod.setAttribute('smd') # set general values text_x = 0. text_y = max([args['pad_y'] / 2., args['part_y'] / 2.]) + args['courtyard'] + 0.75 kicad_mod.append(Text(type='reference', text='REF**', at=[text_x, -text_y], layer='F.SilkS')) kicad_mod.append(Text(type='user', text='%R', at=[text_x, -text_y], layer='F.Fab')) kicad_mod.append(Text(type='value', text=args['name'], at=[text_x, text_y], layer='F.Fab')) # create silkscreen silk_x = args['part_x'] / 2. silk_y = max([args['pad_y'] / 2., args['part_y'] / 2.]) + min(max(0.15, args['courtyard'] - 0.05), 0.2) kicad_mod.append(Line(start=[silk_x, silk_y], end=[-silk_x, silk_y], layer='F.SilkS')) kicad_mod.append(Line(start=[silk_x, -silk_y], end=[-silk_x, -silk_y], layer='F.SilkS')) # create fabrication layer kicad_mod.append(RectLine(start=[args['part_x'] / 2., args['part_y'] / 2.], end=[-args['part_x'] / 2., -args['part_y'] / 2.], layer='F.Fab')) # create courtyard courtyard_x = args['courtyard'] + max([args['pad_spacing'] / 2. + args['pad_x'], args['part_x'] / 2.]) courtyard_y = args['courtyard'] + max([args['pad_y'] / 2., args['part_y'] / 2.]) kicad_mod.append(RectLine(start=[courtyard_x, courtyard_y], end=[-courtyard_x, -courtyard_y], layer='F.CrtYd')) # create pads pad_settings = {'type': Pad.TYPE_SMT, 'shape': Pad.SHAPE_RECT, 'size': [args['pad_x'], args['pad_y']], 'layers': Pad.LAYERS_SMT} pad_x_center = (args['pad_spacing'] + args['pad_x']) / 2. kicad_mod.append(Pad(number=1, at=[-pad_x_center, 0], **pad_settings)) kicad_mod.append(Pad(number=2, at=[pad_x_center, 0], **pad_settings)) # add model kicad_mod.append(Model(filename="{model_dir}.3dshapes/{name}.wrl".format(**args), at=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0])) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{}.kicad_mod'.format(args['name'])) if __name__ == '__main__': parser = ModArgparser(smd_chip) parser.add_parameter("name", type=str, required=True) # the root node of .yml files is parsed as name parser.add_parameter("description", type=str, required=True) parser.add_parameter("tags", type=str, required=True) parser.add_parameter("model_dir", type=str, required=True) parser.add_parameter("courtyard", type=float, required=False, default=0.25) parser.add_parameter("part_x", type=float, required=True) parser.add_parameter("part_y", type=float, required=True) parser.add_parameter("pad_x", type=float, required=True) parser.add_parameter("pad_y", type=float, required=True) parser.add_parameter("pad_spacing", type=float, required=True) parser.run() # now run our script which handles the whole part of parsing the files ================================================ FILE: scripts/pin-headers_socket-strips/make_idc_headers.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_pin_headers import * # NOQA if __name__ == '__main__': # from http://multimedia.3m.com/mws/media/22448O/3m-four-wall-header-3000-series-100-x-100-ts-0772.pdf # and http://www.selecom.it/pdf/06din416.pdf # and https://www.reboul.fr/storage/00003af6.pdf # and http://www.oupiin.com/product_iii.html?c1=10&c2=54 # and http://www.assmann-wsw.com/fileadmin/catalogue/04_Multiflex_rev4-0.pdf # and https://docs.google.com/spreadsheets/d/16SsEcesNF15N3Lb4niX7dcUr-NY5_MFPQhobNuNppn4/edit#gid=0 tags_additional = [] extra_description = 'https://docs.google.com/spreadsheets/d/16SsEcesNF15N3Lb4niX7dcUr-NY5_MFPQhobNuNppn4/edit#gid=0' rm=2.54 cols = 2 ddrill=1 pad=[1.7,1.7] orientation='Vertical' latching = True body_width=8.8 body_overlen=10.97 body_offset=0 mating_overlen=3.92 wall_thickness=1.2 notch_width=4.1 latch_lengths = [0,6.5,9.5,12] # these values roughly represent the referenced parts with the latch open latch_width=4.4 # large enough to handle all referenced parts and measured empirically mh_ddrill=2.69 mh_pad=[8,8] # 3M 3000 datasheet says 5/16" screw head which is ~8mm; existing KiCad footprint is 5.46mm mh_overlen=8.94 # existing KiCad footprint is 8.89 mh_offset=1.02 # existing KiCad footprint is 1.02 mh_number='MP' for rows in [5,6,7,8,10,12,13,15,17,20,25,30,32]: for latch_len in latch_lengths: for mh_ddrill, mh_pad, mh_overlen in zip([0, mh_ddrill], [[0,0], mh_pad], [0, mh_overlen]): #for mh_ddrill, mh_pad, mh_overlen in zip([0], [[0,0]], [0]): makeIdcHeader(rows, cols, rm, rm, body_width, body_overlen, body_overlen, body_offset, ddrill, pad, mating_overlen, wall_thickness, notch_width, orientation, latching, latch_len, latch_width, mh_ddrill, mh_pad, mh_overlen, mh_offset, mh_number, tags_additional, extra_description, "Connector_IDC", "IDC-Header", "IDC header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") # the above datasheets cover both horizontal and vertical # latches are assumed to hang off the PCB so they aren't included here # for this footprint the body outline is hard-coded into the script orientation='Horizontal' body_width=1.24+15.53 # # existing KiCad footprint is 1.27+15.88 body_offset=-1.24 # existing KiCad footprint is -1.27 latch_len=0 mh_ddrill=2.69 # not sure why this needs to be here when it's above... mh_pad=[8,8] # existing KiCad footprint is 3.05mm mh_overlen=5.905 # existing KiCad footprint is 5.84 mh_offset=1.8 # existing KiCad footprint is 1.78 for rows in [5,6,7,8,10,12,13,15,17,20,25,30,32]: for mh_ddrill, mh_pad, mh_overlen in zip([0, mh_ddrill], [[0,0], mh_pad], [0, mh_overlen]): makeIdcHeader(rows, cols, rm, rm, body_width, body_overlen, body_overlen, body_offset, ddrill, pad, mating_overlen, wall_thickness, notch_width, orientation, latching, latch_len, latch_width, mh_ddrill, mh_pad, mh_overlen, mh_offset, mh_number, tags_additional, extra_description, "Connector_IDC", "IDC-Header", "IDC header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") # from http://multimedia.3m.com/mws/media/330367O/3m-four-wall-header-2500-series-ts-0770.pdf # and https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=1761681&DocType=Customer+Drawing&DocLang=English # and https://cdn.amphenol-icc.com/media/wysiwyg/files/drawing/75869.pdf # and https://katalog.we-online.de/em/datasheet/6120xx21621.pdf # and https://docs.google.com/spreadsheets/d/16SsEcesNF15N3Lb4niX7dcUr-NY5_MFPQhobNuNppn4/edit#gid=0 orientation='Vertical' latching = False has_latch=False body_width=8.9 body_overlen=5.1 body_offset=0 mating_overlen=3.91 for rows in [3,4,5,6,7,8,10,12,13,15,17,20,25,30,32]: makeIdcHeader(rows, cols, rm, rm, body_width, body_overlen, body_overlen, body_offset, ddrill, pad, mating_overlen, wall_thickness, notch_width, orientation, latching, 0, 0, 0, [0,0], 0, 0, 0, tags_additional, extra_description, "Connector_IDC", "IDC-Header", "IDC box header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") # from http://multimedia.3m.com/mws/media/22504O/3mtm-100-in-loprof-hdr-100x-100strt-ra-4-wall-ts0818.pdf # and https://b2b.harting.com/files/download/PRD/PDF_TS/09185XXX323_100154466DRW007A.pdf # and http://suddendocs.samtec.com/prints/tst-1xx-xx-xx-x-xx-xx-mkt.pdf # and https://katalog.we-online.de/em/datasheet/6120xx21721.pdf # and https://cdn.amphenol-icc.com/media/wysiwyg/files/drawing/75867.pdf # and https://docs.google.com/spreadsheets/d/16SsEcesNF15N3Lb4niX7dcUr-NY5_MFPQhobNuNppn4/edit#gid=0 orientation='Horizontal' body_offset=4.38 # distance from pin 1 row to the closest edge of the plastic body for rows in [3,4,5,6,7,8,10,12,13,15,17,20,25,30,32]: makeIdcHeader(rows, cols, rm, rm, body_width, body_overlen, body_overlen, body_offset, ddrill, pad, mating_overlen, wall_thickness, notch_width, orientation, latching, 0, 0, 0, [0,0], 0, 0, 0, tags_additional, extra_description, "Connector_IDC", "IDC-Header", "IDC box header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") ================================================ FILE: scripts/pin-headers_socket-strips/make_pin_headers.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_pin_headers import * # NOQA if __name__ == '__main__': # common settings # from http://katalog.we-online.de/em/datasheet/6130xx11121.pdf # and http://katalog.we-online.de/em/datasheet/6130xx21121.pdf # and http://katalog.we-online.de/em/datasheet/6130xx11021.pdf # and http://katalog.we-online.de/em/datasheet/6130xx21021.pdf # and https://cdn.harwin.com/pdfs/M20-877.pdf # and https://cdn.harwin.com/pdfs/M20-876.pdf rm=2.54 ddrill=1 pad=[1.7,1.7] singlecol_packwidth=2.54 singlecol_packoffset=0 angled_pack_width=2.54 angled_pack_offset=1.5 angled_pin_length=6 angled_pin_width=0.64 rmx_pad_offset=[1.655,2.525] rmx_pin_length=[2.54,3.6] pin_width=0.64 single_pad_smd=[2.51,1.0] dual_pad_smd=[3.15,1.0] for cols in [1,2]: for rows in range(1,41): makePinHeadStraight(rows, cols, rm, rm, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, ddrill, pad, [], "/Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadAngled(rows, cols, rm, rm, angled_pack_width, angled_pack_offset, angled_pin_length, angled_pin_width, ddrill, pad, [], "/Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if rows != 1 or cols == 2: if cols == 2: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, dual_pad_smd, True, [], "/Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if cols==1: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, True, [], "/Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, False, [], "/Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") rm=2.00 ddrill=0.8 pad=[1.35, 1.35] singlecol_packwidth=2.0 singlecol_packoffset=0 angled_pack_width=1.5 angled_pack_offset=3-1.5 angled_pin_length=4.2 angled_pin_width=0.5 rmx_pad_offset=[1.175,2.085] rmx_pin_length=[2.1,2.875] pin_width=0.5 single_pad_smd=[2.35,0.85] dual_pad_smd=[2.58,1.0] for cols in [1, 2]: for rows in range(1, 41): makePinHeadStraight(rows, cols, rm, rm, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, ddrill, pad, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadAngled(rows, cols, rm, rm, angled_pack_width, angled_pack_offset, angled_pin_length, angled_pin_width, ddrill, pad, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if rows != 1 or cols == 2: if cols == 2: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, dual_pad_smd, True, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if cols == 1: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, True, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, False, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") # From https://cdn.harwin.com/pdfs/M50-393.pdf # https://cdn.harwin.com/pdfs/M50-363.pdf # https://cdn.harwin.com/pdfs/M50-353.pdf # https://cdn.harwin.com/pdfs/M50-360.pdf # and http://www.mouser.com/ds/2/181/M50-360R-1064294.pdfs rm = 1.27 ddrill = 0.65 pad = [1.0, 1.0] package_width=[2.1,3.41] singlecol_packwidth = 1.27 angled_pack_width=1.0 angled_pack_offset=0.5 angled_pin_length=4.0 angled_pin_width=0.4 rmx_pad_offset=[1.5,1.95] rmx_pin_length=[2.5, 2.75] pin_width=0.4 single_pad_smd=[3.0,0.65] dual_pad_smd=[2.4,0.74] for cols in [1, 2]: for rows in range(1, 41): makePinHeadStraight(rows, cols, rm, rm, package_width[cols-1], singlecol_packwidth / 2 , singlecol_packwidth / 2 , ddrill, pad, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadAngled(rows, cols, rm, rm, angled_pack_width, angled_pack_offset, angled_pin_length, angled_pin_width, ddrill, pad, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if rows != 1 or cols == 2: if cols == 2: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, package_width[cols-1], singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, dual_pad_smd, True, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if cols == 1: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, package_width[cols-1], singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, True, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, package_width[cols-1], singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, False, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") #single row THT Straight headers https://gct.co/pdfjs/web/viewer.html?file=/Files/Drawings/BC020.pdf&t=1502019369628 #dual row THT Straight headers https://gct.co/files/drawings/bc035.pdf #single row THT Angled headers https://gct.co/pdfjs/web/viewer.html?file=/Files/Drawings/BC030.pdf&t=1502031327147 #dual row THT Angled headers https://gct.co/files/drawings/bc045.pdf #single row SMD Straight headers http://www.farnell.com/datasheets/1912818.pdf?_ga=2.101918145.1303212991.1501602361-984110936.1498471838 #dual row SMD Straight headers https://gct.co/files/drawings/bc050.pdf rm = 1.0 ddrill = 0.5 pad = [0.85, 0.85] package_width=[1.27,2.3] singlecol_packwidth = 1.00 angled_pack_width=[1.0, 1.2] angled_pack_offset= [0.25, 0.9] angled_pin_length=2.0 angled_pin_width=0.3 rmx_pad_offset=[0.875, 1.65] rmx_pin_length=[1.25, 2.4] pin_width=0.3 single_pad_smd=[1.75,0.6] dual_pad_smd=[2.0,0.5] for cols in [1, 2]: for rows in range(1, 41): makePinHeadStraight(rows, cols, rm, rm, package_width[cols-1], singlecol_packwidth / 2 , singlecol_packwidth / 2 , ddrill, pad, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadAngled(rows, cols, rm, rm, angled_pack_width[cols-1], angled_pack_offset[cols-1], angled_pin_length, angled_pin_width, ddrill, pad, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if rows != 1 or cols == 2: if cols == 2: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, package_width[cols-1], singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, dual_pad_smd, True, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") if cols == 1: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, package_width[cols-1], singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, True, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset[cols-1], rmx_pin_length[cols-1], pin_width, package_width[cols-1], singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, single_pad_smd, False, [], "Pin_Headers", "Pin_Header", "pin header", [0, 0, 0], [1, 1, 1], [0, 0, 0], "${KISYS3DMOD}") ================================================ FILE: scripts/pin-headers_socket-strips/make_socket_strips.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","tools")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_scripts_pin_headers import * # NOQA if __name__ == '__main__': # common settings rm=2.54 ddrill=1 pad=[1.7,1.7] singlecol_packwidth=2.54 singlecol_packoffset=0 angled_pack_width=8.51 angled_pack_offset=1.52 angled_pin_width=0.64 rmx_pad_offset=1.25 rmx_pin_length=2.65 pin_width=0.64 pad_smd=[3,1] for cols in [1,2]: for rows in range(1,41): makePinHeadStraight(rows, cols, rm, rm, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, ddrill, pad, [], "Socket_Strips", "Socket_Strip", "socket strip", [-(cols - 1) * rm / 2 / 25.4, -(rows - 1) * rm / 2 / 25.4, 0], [1, 1, 1], [0, 0, 270], isSocket=True) makeSocketStripAngled(rows, cols, rm, rm, angled_pack_width, angled_pack_offset, angled_pin_width, ddrill, pad, [], "Socket_Strips", "Socket_Strip", "socket strip",[-(cols - 1) * rm / 2 / 25.4, -(rows - 1) * rm / 2 / 25.4, 0], [1, 1, 1], [0, 0, 270]) if cols == 2: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset, rmx_pin_length, pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, pad_smd, True, [], "Socket_Strips", "Socket_Strip", "socket strip", isSocket=True) rm=2.00 ddrill=0.8 pad=[1.35, 1.35] singlecol_packwidth=2.0 singlecol_packoffset=0 angled_pack_width=6.35 angled_pack_offset=1.27 angled_pin_width=0.5 rmx_pad_offset=2.125 rmx_pin_length=2 pin_width=0.5 pad_smd=[2.75,1] for cols in [1, 2]: for rows in range(1, 41): makePinHeadStraight(rows, cols, rm, rm, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, ddrill, pad, [], "Socket_Strips", "Socket_Strip", "socket strip", offset3d=[0,0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], isSocket=True) makeSocketStripAngled(rows, cols, rm, rm, angled_pack_width, angled_pack_offset, angled_pin_width, ddrill, pad, [], "Socket_Strip", "Socket_Strip", "socket strip", [(cols - 1) * rm / 2 / 25.4, -(rows - 1) * rm / 2 / 25.4, 0], [1, 1, 1], [0, 0, 90]) if cols == 2: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset, rmx_pin_length, pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, pad_smd, True, [], "Socket_Strips", "Socket_Strip", "socket strip", isSocket=True) rm = 1.27 ddrill = 0.7 pad = [1, 1] package_width=[2.54,3.05] singlecol_packwidth = 1.27 angled_pack_width=1 angled_pack_offset=3.81-1 angled_pin_length=3.81 angled_pin_width=0.4 rmx_pad_offset=1.95 rmx_pin_length=1.92 pin_width=0.4 pad_smd=[2.1,0.75] for cols in [1, 2]: for rows in range(1, 41): makePinHeadStraight(rows, cols, rm, rm, package_width[cols-1], singlecol_packwidth / 2 , singlecol_packwidth / 2 , ddrill, pad, [], "Socket_Strips", "Socket_Strip", "socket strip", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], isSocket=True) if cols == 2: makePinHeadStraightSMD(rows, cols, rm, rm, rmx_pad_offset, rmx_pin_length, pin_width, cols * singlecol_packwidth + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, singlecol_packwidth / 2 + singlecol_packoffset, pad_smd, True, [], "Socket_Strips", "Socket_Strip", "socket strip", isSocket=True) ================================================ FILE: scripts/tools/dict_tools.py ================================================ #!/usr/bin/env python import collections.abc import copy def dictMerge(a, b): """Recursively merges the contents of two dict objects This function is similar to the built-in dict.update() method, but instead of clobbering the contents of one dictionary with another, it recursively combines dictionaries. The result is a dictionary containing the combined contents of the arguments. If both dictionaries contain a key with the same name (at the same level), the value in `b` takes precedence. Parameters ---------- a : dict Base dictionary used as the merge destination b : dict Dictionary containing values to merge into `a` Returns ------- Merged dictionaries (`a` with contents updated from `b`) Examples -------- >>> a = {'a': 1, 'b': 2, 'c': {'a': 1, 'b': 2}} >>> b = {'c': {'b': 3}, 'd': 4} >>> dictMerge(a, b) {'a': 1, 'b': 2, 'c': {'a': 1, 'b': 3}, 'd': 4} """ for (k, v) in b.items(): if isinstance(v, collections.abc.Mapping): a[k] = dictMerge(a.get(k, {}), v) else: a[k] = v return a def dictInherit(d): """Recursively merges dictionaries within a hierarchy using 'inherit' entries The top-level dictionary (`d`) can be thought of as a type of "namespace" containing a collection of objects (sub-dictionaries). Objects within the namespace may contain an 'inherit' entry, which stores the key for another object within the namespace. Inheritance is done recursively, so it is possible to have multiple levels of inheritance (object c can inherit b, which itself inherits from a). When this function is executed, it iterates through every entry in `d` and runs dictMerge() until all of the 'inherit' entries have been resolved. The result is applied to `d` in-place. Parameters ---------- d : dict Top-level "namespace" dictionary containing other dictionaries, each of which may contain an 'inherit' key to be resolved; edited in-place Raises ------ RecursionError If two dictionaries attempt to inherit each other KeyError If a dictionary tries to inherit from a key that is not in `d` Notes ----- Typical JSON/YAML file structure that can be processed by this function: { "1": { "a": 1, "b": {"c": 2, "d": 3, ...} }, "2": { "inherit": "1", "b": {"c": 3} }, ... "n": { "inherit": "2", "d": 4 } } The result will look something like this: { "1": { "a": 1, "b": {"c": 2, "d": 3, ...} }, "2": { "a": 1, "b": {"c": 3, "d": 3, ...} }, ... "n": { "a": 1, "b": {"c": 3, "d": 3, ...}, "d": 4 } } """ def dictInherit(d, child, parent): if 'inherit' not in parent: del child['inherit'] p = copy.deepcopy(parent) return dictMerge(p, child) elif d[parent['inherit']] is child: raise RecursionError else: return dictInherit(d, parent, d[parent['inherit']]) for (k, v) in d.items(): if isinstance(v, collections.abc.Mapping) and 'inherit' in v: d[k] = dictInherit(d, v, d[v['inherit']]) else: continue ================================================ FILE: scripts/tools/drawing_tools.py ================================================ #!/usr/bin/env python import sys import os import math import time # ensure that the kicad-footprint-generator directory is available # sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory # sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0], "..", "..", "kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0], "..", "..")) # load kicad_mod path from KicadModTree import * # NOQA from footprint_global_properties import * # tool function for generating 3D-scripts def script3d_writevariable(file, line, varname, value): file.write("# {0}\nApp.ActiveDocument.Spreadsheet.set('A{1}', 'var {0} = '); App.ActiveDocument.Spreadsheet.set('B{1}', '{2}'); App.ActiveDocument.Spreadsheet.setAlias('B{1}', '{0}')\n".format(varname, line, value)) # round for grid g def roundG(x, g): if (x > 0): return math.ceil(x / g) * g else: return math.floor(x / g) * g # round for grid g def sqr(x): return x*x # round for courtyard grid def roundCrt(x): return roundG(x, grid_crt) # float-variant of range() def frange(x, y, jump): while x < y: yield x x += jump # inclusice float-variant of range() def frangei(x, y, jump): while x <= y: yield x x += jump # returns a list with a single rectangle around x,y with width and height w and h def addKeepoutRect(x, y, w, h): return [[x - w / 2, x + w / 2, y - h / 2, y + h / 2]] # returns a series of rectangle that lie around the circular pad around (x,y) with radius w=h # if w!=h, addKeepoutRect() is called def addKeepoutRound(x, y, w, h): if w != h: return addKeepoutRect(x, y, w, h) else: res = [] Nrects = 16 r = max(h, w) / 2 yysum = 0 for ya in frange(0, r, r / Nrects): a = math.fabs(math.asin(ya / r) / math.pi * 180) yy = math.fabs(r * math.sin(a / 180.0 * math.pi)) xx = math.fabs(r * math.cos(a / 180.0 * math.pi)) if (xx > 0): res.append([x - xx - 0.015, x + xx + 0.015, y - yy - r / Nrects - 0.015, y - yy + .015]) res.append([x - xx - 0.015, x + xx + 0.015, y + yy - 0.015, y + yy + r / Nrects + 0.015]) yysum = yysum + yy return res # internal method for keepout-processing def applyKeepouts(lines_in, y, xi, yi, keepouts): # print(" applyKeepouts(\n lines_in=", lines_in, " \n y=", y, " \n xi=", xi, " yi=", yi, " \n keepouts=", keepouts, ")") lines = lines_in changes = True while (changes): changes = False for ko in keepouts: ko = [min(ko[0], ko[1]), max(ko[0], ko[1]), min(ko[2], ko[3]), max(ko[2], ko[3])] if (ko[yi + 0] <= y) and (y <= ko[yi + 1]): # print(" INY: koy=", [ko[yi + 0], ko[yi + 1]], " y=", y, "): kox=", [ko[xi + 0], ko[xi + 1]]) for li in reversed(range(0, len(lines))): l = lines[li] if (l[0] >= ko[xi + 0]) and (l[0] <= ko[xi + 1]) and (l[1] >= ko[xi + 0]) and ( l[1] <= ko[xi + 1]): # Line completely inside -> remove lines.pop(li) # print(" H1: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, ")") changes = True elif (l[0] >= ko[xi + 0]) and (l[0] <= ko[xi + 1]) and ( l[1] > ko[ xi + 1]): # Line starts inside, but ends outside -> remove and add shortened lines.pop(li) lines.append([ko[xi + 1], l[1]]) # print(" H2: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ", [ko[xi+1], l[1]]) changes = True elif (l[0] < ko[xi + 0]) and (l[1] <= ko[xi + 1]) and ( l[1] >= ko[ xi + 0]): # Line starts outside, but ends inside -> remove and add shortened lines.pop(li) lines.append([l[0], ko[xi + 0]]) # print(" H3: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ", [l[0], ko[xi+0]]) changes = True elif (l[0] < ko[xi + 0]) and ( l[1] > ko[ xi + 1]): # Line starts outside, and ends outside -> remove and add 2 shortened lines.pop(li) lines.append([l[0], ko[xi + 0]]) lines.append([ko[xi + 1], l[1]]) # print(" H4: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ", [l[0], ko[xi+0]], [ko[xi+1], l[1]]) changes = True # else: # print(" USE: ko=", [ko[xi+0],ko[xi+1]], " li=", li, " l=", l, "): ") if changes: break return lines # gives True if the given point (x,y) is contained in any keepout def containedInAnyKeepout(x,y, keepouts): for ko in keepouts: ko = [min(ko[0], ko[1]), max(ko[0], ko[1]), min(ko[2], ko[3]), max(ko[2], ko[3])] if x>=ko[0] and x<=ko[1] and y>=ko[2] and y<=ko[3]: #print("HIT!") return True #print("NO HIT ",x,y) return False # draws the keepouts def debug_draw_keepouts(kicad_modg, keepouts): for ko in keepouts: kicad_modg.append(RectLine(start=[ko[0],ko[2]], end=[ko[1],ko[3]], layer='F.Mask', width=0.01)) # split a horizontal line so it does not interfere with keepout areas defined as [[x0,x1,y0,y1], ...] def addHLineWithKeepout(kicad_mod, x0, x1, y, layer, width, keepouts=[], roun=0.001, dashed=False): if dashed: addHDLineWithKeepout(kicad_mod, x0, x1, y, layer, width, keepouts, roun) else: # print("addHLineWithKeepout",y) linesout = applyKeepouts([[min(x0, x1), max(x0, x1)]], y, 0, 2, keepouts) for l in linesout: kicad_mod.append( Line(start=[roundG(l[0], roun), roundG(y, roun)], end=[roundG(l[1], roun), roundG(y, roun)], layer=layer,width=width)) # draw a circle minding the keepouts def addCircleWithKeepout(kicad_mod, x, y, radius, layer, width, keepouts=[], roun=0.001): dalpha = 2 * 3.1415 / (360) a = 0 start=0 startx=x + radius * math.sin(0) starty=y + radius * math.cos(0) hasToDraw=False noneUsed=True while a < 2 * 3.1415: x1 = x + radius * math.sin(a) y1 = y + radius * math.cos(a) if containedInAnyKeepout(x1,y1, keepouts): if hasToDraw and math.fabs(a-start)>0: kicad_mod.append( Arc(center=[roundG(x, roun), roundG(y, roun)], start=[roundG(startx, roun), roundG(starty, roun)], angle=-1*(a - start)/3.1415*180, layer=layer, width=width)) hasToDraw = False startx=x1; starty=y1; start=a noneUsed = False else: hasToDraw = True a = a + dalpha if noneUsed: kicad_mod.append( Circle(center=[roundG(x, roun), roundG(y, roun)], radius=radius, layer=layer, width=width)) elif hasToDraw and math.fabs(a - start) > 0: kicad_mod.append( Arc(center=[roundG(x, roun), roundG(y, roun)], start=[roundG(startx, roun), roundG(starty, roun)], angle=-1*(a - start)/3.1415*180, layer=layer, width=width)) # draw an arc def addArcByAngles(kicad_mod, x, y, radius, angle_start, angle_end, layer, width, roun=0.001): startx = x + radius * math.sin(angle_start/180*3.1415) starty = y + radius * math.cos(angle_start/180*3.1415) kicad_mod.append( Arc(center=[roundG(x, roun), roundG(y, roun)], start=[roundG(startx, roun), roundG(starty, roun)], angle=-(angle_end-angle_start), layer=layer, width=width)) # draw an arc minding the keepouts def addArcByAnglesWithKeepout(kicad_mod, x, y, radius, angle_start, angle_end, layer, width, keepouts=[], roun=0.001): startx = x + radius * math.sin(angle_start/180*3.1415) starty = y + radius * math.cos(angle_start/180*3.1415) addArcWithKeepout(kicad_mod, x, y, startx, starty, -(angle_end-angle_start), layer, width, keepouts, roun) # draw an arc minding the keepouts def addArcWithKeepout(kicad_mod, x, y, startx, starty, angle, layer, width, keepouts=[], roun=0.001): dalpha = angle/180*3.1415 / (360) radius=math.sqrt(sqr(x-startx)+sqr(y-starty)); a = math.asin((startx-x)/radius) if starty<0: a=a+3.1415/2 astart=a; aend=astart+angle/180*3.1415 start=astart #print(radius, astart/3.1415*180, aend/3.1415*180) istartx=x + radius * math.sin(a) istarty=y + radius * math.cos(a) hasToDraw=False noneUsed=True while a < aend: x1 = x + radius * math.sin(a) y1 = y + radius * math.cos(a) if containedInAnyKeepout(x1,y1, keepouts): if hasToDraw and math.fabs(a-start)>0: #print('DRAW ',x1,y1) kicad_mod.append( Arc(center=[roundG(x, roun), roundG(y, roun)], start=[roundG(istartx, roun), roundG(istarty, roun)], angle=-1*(a - start)/3.1415*180, layer=layer, width=width)) hasToDraw = False istartx=x1; istarty=y1; start=a noneUsed = False else: hasToDraw = True #print(a, dalpha, hasToDraw, noneUsed) a = a + dalpha if noneUsed: kicad_mod.append( Arc(center=[roundG(x, roun), roundG(y, roun)], start=[roundG(startx, roun), roundG(starty, roun)], angle=angle, layer=layer, width=width)) elif hasToDraw and math.fabs(a - start) > 0: kicad_mod.append( Arc(center=[roundG(x, roun), roundG(y, roun)], start=[roundG(istartx, roun), roundG(istarty, roun)], angle=-1*(a - start)/3.1415*180, layer=layer, width=width)) # draw an ellipse with one axis along x-axis and one axis along y-axis and given width/height def addEllipse(kicad_mod, x, y, w, h, layer, width, roun=0.001): factor=h/w alpha=math.atan(h/w)*2 radius=w/2/math.sin(alpha) addArcByAngles(kicad_mod=kicad_mod, x=x, y=y+radius*math.cos(alpha), radius=radius, angle_start=180-alpha/3.1415*180, angle_end=180+alpha/3.1415*180, layer=layer, width=width, roun=roun); addArcByAngles(kicad_mod=kicad_mod, x=x, y=y-radius*math.cos(alpha), radius=radius, angle_start=alpha/3.1415*180, angle_end=-alpha/3.1415*180, layer=layer, width=width, roun=roun); # draw an ellipse with one axis along x-axis and one axis along y-axis and given width/height def addEllipseWithKeepout(kicad_mod, x, y, w, h, layer, width, keepouts=[], roun=0.001): factor=h/w alpha=math.atan(h/w)*2 radius=w/2/math.sin(alpha) addArcByAnglesWithKeepout(kicad_mod=kicad_mod, x=x, y=y+radius*math.cos(alpha), radius=radius, angle_start=180-alpha/3.1415*180, angle_end=180+alpha/3.1415*180, keepouts=keepouts, layer=layer, width=width, roun=roun); addArcByAnglesWithKeepout(kicad_mod=kicad_mod, x=x, y=y-radius*math.cos(alpha), radius=radius, angle_start=alpha/3.1415*180, angle_end=-alpha/3.1415*180, keepouts=keepouts, layer=layer, width=width, roun=roun); # split a circle so it does not interfere with keepout areas defined as [[x0,x1,y0,y1], ...] def addDCircleWithKeepout(kicad_mod, x, y, radius, layer, width, keepouts=[], roun=0.001): dalpha = 2 * 3.1415 / (2 * 3.1415 * radius / (6 * width)) a = 0 while a < 2 * 3.1415: x1 = x + radius * math.sin(a) y1 = y + radius * math.cos(a) x2 = x + radius * math.sin(a + dalpha / 2) y2 = y + radius * math.cos(a + dalpha / 2) ok=True aa=a while aa1: for p in range(0, len(poly)-1): addLineWithKeepout(kicad_mod, poly[p][0], poly[p][1], poly[p+1][0], poly[p+1][1], layer, width, keepouts, roun) # add a dashed circle def addDCircle(kicad_mod, x, y, radius, layer, width, roun=0.001): dalpha = 2 * 3.1415 / (2 * 3.1415 * radius / (6 * width)) a = 0 while a < 2 * 3.1415: x1 = x + radius * math.sin(a) y1 = y + radius * math.cos(a) x2 = x + radius * math.sin(a + dalpha / 2) y2 = y + radius * math.cos(a + dalpha / 2) kicad_mod.append(Arc(center=[roundG(x, roun), roundG(y, roun)], start=[roundG(x1, roun), roundG(y1, roun)], angle=dalpha / 2 / 3.1415 + 180, layer=layer, width=width)) a = a + dalpha # draw a circle with a screw slit under 45 degrees def addSlitScrew(kicad_mod, x, y, radius, layer, width, roun=0.001): kicad_mod.append(Circle(center=[roundG(x, roun), roundG(y, roun)], radius=radius, layer=layer, width=width)) da = 5 dx1 = 0.99 * radius * math.sin((135 - da) / 180 * 3.1415) dy1 = 0.99 * radius * math.cos((135 - da) / 180 * 3.1415) dx2 = 0.99 * radius * math.sin((135 + da) / 180 * 3.1415) dy2 = 0.99 * radius * math.cos((135 + da) / 180 * 3.1415) dx3 = 0.99 * radius * math.sin((315 - da) / 180 * 3.1415) dy3 = 0.99 * radius * math.cos((315 - da) / 180 * 3.1415) dx4 = 0.99 * radius * math.sin((315 + da) / 180 * 3.1415) dy4 = 0.99 * radius * math.cos((315 + da) / 180 * 3.1415) # print(x,y,dx1,dy1,dx4,dy4) kicad_mod.append(Line(start=[roundG(x + dx1, roun), roundG(y + dy1, roun)], end=[roundG(x + dx4, roun), roundG(y + dy4, roun)], layer=layer, width=width)) kicad_mod.append(Line(start=[roundG(x + dx2, roun), roundG(y + dy2, roun)], end=[roundG(x + dx3, roun), roundG(y + dy3, roun)], layer=layer, width=width)) # draw a circle with a screw slit under 45 degrees def addSlitScrewWithKeepouts(kicad_mod, x, y, radius, layer, width, keepouts, roun=0.001): addCircleWithKeepout(kicad_mod, x, y, radius, layer, width, keepouts, roun) da = 5 dx1 = 0.99 * radius * math.sin((135 - da) / 180 * 3.1415) dy1 = 0.99 * radius * math.cos((135 - da) / 180 * 3.1415) dx2 = 0.99 * radius * math.sin((135 + da) / 180 * 3.1415) dy2 = 0.99 * radius * math.cos((135 + da) / 180 * 3.1415) dx3 = 0.99 * radius * math.sin((315 - da) / 180 * 3.1415) dy3 = 0.99 * radius * math.cos((315 - da) / 180 * 3.1415) dx4 = 0.99 * radius * math.sin((315 + da) / 180 * 3.1415) dy4 = 0.99 * radius * math.cos((315 + da) / 180 * 3.1415) # print(x,y,dx1,dy1,dx4,dy4) addLineWithKeepout(kicad_mod,x + dx1, y + dy1, x + dx4, y + dy4, layer, width, keepouts) addLineWithKeepout(kicad_mod, x + dx2, y + dy2, x + dx3, y + dy3, layer, width, keepouts) # draw a circle with a cross-screw under 45 deg def addCrossScrew(kicad_mod, x, y, radius, layer, width, roun=0.001): kicad_mod.append(Circle(center=[roundG(x, roun), roundG(y, roun)], radius=radius, layer=layer, width=width)) kkt = Translation(x, y) kicad_mod.append(kkt) dd = radius * 0.1 / 2 dw = 0.8 * radius kkt.append(PolygoneLine(polygone=[[roundG(-dw, roun), roundG(-dd, roun)], [roundG(-dd, roun), roundG(-dd, roun)], [roundG(-dd, roun), roundG(-dw, roun)], [roundG(+dd, roun), roundG(-dw, roun)], [roundG(+dd, roun), roundG(-dd, roun)], [roundG(+dw, roun), roundG(-dd, roun)], [roundG(+dw, roun), roundG(+dd, roun)], [roundG(+dd, roun), roundG(+dd, roun)], [roundG(+dd, roun), roundG(+dw, roun)], [roundG(-dd, roun), roundG(+dw, roun)], [roundG(-dd, roun), roundG(+dd, roun)], [roundG(-dw, roun), roundG(+dd, roun)], [roundG(-dw, roun), roundG(-dd, roun)]], layer=layer, width=width)) # draw a circle with a cross-screw under 45 deg def addCrossScrewWithKeepouts(kicad_mod, x, y, radius, layer, width, keepouts=[], roun=0.001): addCircleWithKeepout(kicad_mod, x, y, radius, layer, width, keepouts, roun) kkt = Translation(x, y) kicad_mod.append(kkt) dd = radius * 0.1 / 2 dw = 0.8 * radius polygone = [[roundG(-dw, roun), roundG(-dd, roun)], [roundG(-dd, roun), roundG(-dd, roun)], [roundG(-dd, roun), roundG(-dw, roun)], [roundG(+dd, roun), roundG(-dw, roun)], [roundG(+dd, roun), roundG(-dd, roun)], [roundG(+dw, roun), roundG(-dd, roun)], [roundG(+dw, roun), roundG(+dd, roun)], [roundG(+dd, roun), roundG(+dd, roun)], [roundG(+dd, roun), roundG(+dw, roun)], [roundG(-dd, roun), roundG(+dw, roun)], [roundG(-dd, roun), roundG(+dd, roun)], [roundG(-dw, roun), roundG(+dd, roun)], [roundG(-dw, roun), roundG(-dd, roun)]]; addPolyLineWithKeepout(kicad_mod, polygone, layer, width, keepouts) # split a vertical line so it does not interfere with keepout areas defined as [[x0,x1,y0,y1], ...] def addVLineWithKeepout(kicad_mod, x, y0, y1, layer, width, keepouts=[], roun=0.001, dashed=False): if dashed: addVDLineWithKeepout(kicad_mod, x, y0, y1, layer, width, keepouts, roun) else: # print("addVLineWithKeepout",x) linesout = applyKeepouts([[min(y0, y1), max(y0, y1)]], x, 2, 0, keepouts) for l in linesout: kicad_mod.append( Line(start=[roundG(x, roun), roundG(l[0], roun)], end=[roundG(x, roun), roundG(l[1], roun)], layer=layer, width=width)) # split a dashed horizontal line so it does not interfere with keepout areas defined as [[x0,x1,y0,y1], ...] def addHDLineWithKeepout(kicad_mod, x0, x1, y, layer, width, keepouts=[], roun=0.001): dx=3*width x=min(x0,x1) while x def allTrapezoid(model, x, size, angle, layer, width): dx=size[1]*math.tan(math.fabs(angle)/180*math.pi) if angle == 0: model.append(RectLine(start=x, end=[x[0] + size[0], x[1] + size[1]], layer=layer, width=width)) elif angle<0: model.append(PolygoneLine(polygone=[[x[0] + dx, x[1]], [x[0] + size[0] - dx, x[1]], [x[0] + size[0], x[1] + size[1]], [x[0], x[1] + size[1] ], [x[0] + dx, x[1]]], layer=layer, width=width)) elif angle>0: model.append(PolygoneLine(polygone=[[x[0], x[1]], [x[0] + size[0], x[1]], [x[0] + size[0]-dx, x[1] + size[1]], [x[0] + dx, x[1] + size[1] ], [x[0] , x[1]]], layer=layer, width=width)) # draw a downward equal-sided triangle def allEqualSidedDownTriangle(model, xcenter, side_length, layer, width): h=sqrt(3)/6*side_length model.append(PolygoneLine(polygone=[[xcenter[0]-side_length/2, xcenter[1]-h], [xcenter[0]+side_length/2, xcenter[1]-h], [xcenter[0], xcenter[1]+2*h], [xcenter[0]-side_length/2, xcenter[1]-h], ], layer=layer, width=width)) # draw a trapezoid with a given angle of the vertical lines and rounded corners # # angle<0 # /---------------------\ ^ # / \ | # / \ size[1] # / \ | # /-----------------------------\ v # <------------size[0]----------> def allRoundedBevelRect(model, x, size, angle, corner_radius, layer, width): if corner_radius<=0: allTrapezoid(model,x,size,angle,layer,width) else: dx=size[1]*math.tan(math.fabs(angle)/180*math.pi) dx2=corner_radius*math.tan((90-math.fabs(angle))/2/180*math.pi) dx3=corner_radius/math.tan((90-math.fabs(angle))/2/180*math.pi) ds2=corner_radius*math.sin(math.fabs(angle)/180*math.pi) dc2=corner_radius*math.cos(math.fabs(angle)/180*math.pi) if angle == 0: addRoundedRect(model, x, size, corner_radius, layer, width=0.2) elif angle<0: ctl=[x[0] +dx+dx2, x[1]+corner_radius] ctr=[x[0] + size[0]-dx-dx2, x[1]+corner_radius] cbl=[x[0] +dx3, x[1]+size[1]-corner_radius] cbr=[x[0] + size[0]-dx3, x[1]+size[1]-corner_radius] model.append(Arc(center=ctl, start=[ctl[0], x[1]], angle=-(90-math.fabs(angle)),layer=layer, width=width)) model.append(Arc(center=ctr, start=[ctr[0], x[1]], angle=(90-math.fabs(angle)),layer=layer, width=width)) model.append(Arc(center=cbl, start=[cbl[0], x[1]+size[1]], angle=(90+math.fabs(angle)),layer=layer, width=width)) model.append(Arc(center=cbr, start=[cbr[0], x[1]+size[1]], angle=-(90+math.fabs(angle)),layer=layer, width=width)) model.append(Line(start=[ctl[0], x[1]], end=[ctr[0], x[1]], layer=layer, width=width)) model.append(Line(start=[cbl[0], x[1]+size[1]], end=[cbr[0], x[1]+size[1]], layer=layer, width=width)) model.append(Line(start=[ctr[0]+dc2,ctr[1]-ds2], end=[cbr[0]+dc2,cbr[1]-ds2], layer=layer, width=width)) model.append(Line(start=[ctl[0]-dc2,ctl[1]-ds2], end=[cbl[0]-dc2,cbl[1]-ds2], layer=layer, width=width)) elif angle>0: cbl=[x[0] +dx+dx2, x[1]+size[1]-corner_radius] cbr=[x[0] + size[0]-dx-dx2, x[1]+size[1]-corner_radius] ctl=[x[0] +dx3, x[1]+corner_radius] ctr=[x[0] + size[0]-dx3, x[1]+corner_radius] model.append(Arc(center=ctl, start=[ctl[0], x[1]], angle=-(90+math.fabs(angle)),layer=layer, width=width)) model.append(Arc(center=ctr, start=[ctr[0], x[1]], angle=(90+math.fabs(angle)),layer=layer, width=width)) model.append(Arc(center=cbl, start=[cbl[0], x[1]+size[1]], angle=(90-math.fabs(angle)),layer=layer, width=width)) model.append(Arc(center=cbr, start=[cbr[0], x[1]+size[1]], angle=-(90-math.fabs(angle)),layer=layer, width=width)) model.append(Line(start=[ctl[0], x[1]], end=[ctr[0], x[1]], layer=layer, width=width)) model.append(Line(start=[cbl[0], x[1]+size[1]], end=[cbr[0], x[1]+size[1]], layer=layer, width=width)) model.append(Line(start=[ctr[0]+dc2,ctr[1]+ds2], end=[cbr[0]+dc2,cbr[1]+ds2], layer=layer, width=width)) model.append(Line(start=[ctl[0]-dc2,ctl[1]+ds2], end=[cbl[0]-dc2,cbl[1]+ds2], layer=layer, width=width)) # draw a rectangle with rounded corners on all sides (e.g. for crystals), or a simple rectangle if bevel_size0=0) # # /----\ # / \ # | | # | | # | | # | | # | | # \ / # \----/ def addRoundedRect(model, x, size, corner_radius, layer, width=0.2): if corner_radius <= 0: model.append(RectLine(start=x, end=[x[0] + size[0], x[1] + size[1]], layer=layer, width=width)) else: model.append(Line(start=[x[0] + corner_radius, x[1]], end=[x[0] + size[0] - corner_radius, x[1]], layer=layer, width=width)) model.append(Line(start=[x[0] + size[0], x[1] + corner_radius], end=[x[0] + size[0], x[1] + size[1] - corner_radius], layer=layer, width=width)) model.append(Line(start=[x[0] + size[0] - corner_radius, x[1] + size[1]], end=[x[0] + corner_radius, x[1] + size[1]], layer=layer, width=width)) model.append(Line(start=[x[0], x[1] + size[1] - corner_radius], end=[x[0], x[1] + corner_radius], layer=layer, width=width)) model.append(Arc(center=[x[0]+corner_radius, x[1] +corner_radius], start=[x[0], x[1] +corner_radius], angle=90, layer=layer, width=width)) model.append(Arc(center=[x[0]+ size[0]-corner_radius, x[1] +corner_radius], start=[x[0]+ size[0]-corner_radius, x[1]], angle=90, layer=layer, width=width)) model.append(Arc(center=[x[0]+corner_radius, x[1] +size[1]-corner_radius], start=[x[0], x[1] +size[1]-corner_radius], angle=-90, layer=layer, width=width)) model.append(Arc(center=[x[0]+ size[0]-corner_radius, x[1] +size[1]-corner_radius], start=[x[0]+ size[0], x[1] +size[1]-corner_radius], angle=90, layer=layer, width=width)) # draws a filled circle consisting of concentric circles of varying widths (e.g. for glue dots!) def fillCircle(model, center, radius, layer, width): model.append(Circle(center=center, radius=radius, layer=layer, width=width)) r = radius w = radius / 3 r = radius - w / 2 while r > w / 2: if r - 0.9 * w <= w / 2: model.append(Circle(center=center, radius=r, layer=layer, width=r * 2)) else: model.append(Circle(center=center, radius=r, layer=layer, width=w)) r = r - 0.9 * w # +------+ # / | # / | # | | # | | # | | # | | # +--------+ # # def bevelRectTL(model, x, size, layer, width, bevel_size=1): model.append(PolygoneLine( polygone=[[x[0] + bevel_size, x[1]], [x[0] + size[0], x[1]], [x[0] + size[0], x[1] + size[1]], [x[0], x[1] + size[1]], [x[0], x[1] + bevel_size], [x[0] + bevel_size, x[1]]], layer=layer, width=width)) # +--------+ # | | # | | # | | # | | # \ | # \ | # +------+ # # def bevelRectBL(model, x, size, layer, width, bevel_size=1): model.append(PolygoneLine(polygone=[[x[0], x[1]], [x[0] + size[0], x[1]], [x[0] + size[0], x[1] + size[1]], [x[0] + bevel_size, x[1] + size[1]], [x[0], x[1] + size[1] - bevel_size], [x[0], x[1]]], layer=layer, width=width)) # draws a DIP-package with half-circle at the top # # +----------+ # | \ / | # | ~~ | # | | # | | # | | # | | # +----------+ def DIPRectT(model, x, size, layer, width, marker_size=2): model.append(PolygoneLine( polygone=[[x[0] + size[0] / 2 - marker_size / 2, x[1]], [x[0], x[1]], [x[0], x[1] + size[1]], [x[0] + size[0], x[1] + size[1]], [x[0] + size[0], x[1]], [x[0] + size[0] / 2 + marker_size / 2, x[1]]], layer=layer, width=width)) model.append(Arc(center=[x[0] + size[0] / 2, x[1]], start=[x[0] + size[0] / 2 - marker_size / 2, x[1]], angle=-180, layer=layer, width=width)) # draws a DIP-package with half-circle at the left # # +---------------+ # |-\ | # | | | # |-/ | # +---------------+ def DIPRectL(model, x, size, layer, width, marker_size=2): model.append(PolygoneLine(polygone=[[x[0], x[1] + size[1] / 2 - marker_size / 2], [x[0], x[1]], [x[0] + size[0], x[1]], [x[0] + size[0], x[1] + size[1]], [x[0], x[1] + size[1]], [x[0], x[1] + size[1] / 2 + marker_size / 2]], layer=layer, width=width)) model.append(Arc(center=[x[0], x[1] + size[1] / 2], start=[x[0], x[1] + size[1] / 2 - marker_size / 2], angle=180, layer=layer, width=width)) # draws the left part of a DIP-package with half-circle at the left # # +-------- # |-\ # | | # |-/ # +-------- def DIPRectL_LeftOnly(model, x, size, layer, width, marker_size=2): model.append(Line(start=[x[0], x[1] + size[1] / 2 - marker_size / 2], end=[x[0], x[1]], layer=layer, width=width)) model.append( Line(start=[x[0], x[1] + size[1]], end=[x[0], x[1] + size[1] / 2 + marker_size / 2], layer=layer, width=width)) if size[0] > 0: model.append(Line(start=[x[0], x[1]], end=[x[0] + size[0], x[1]], layer=layer, width=width)) model.append(Line(start=[x[0], x[1] + size[1]], end=[x[0] + size[0], x[1] + size[1]], layer=layer, width=width)) model.append(Arc(center=[x[0], x[1] + size[1] / 2], start=[x[0], x[1] + size[1] / 2 - marker_size / 2], angle=180, layer=layer, width=width)) # draws a THT quartz footprint (HC49) with a rect around it # +-------------------------+ # | | # | +----------------+ | # | / \ | # | \ / | # | +----------------+ | # | | # +-------------------------+ def THTQuartzRect(model, x, size, inner_size, layer, width): model.append(RectLine(start=x, end=[x[0] + size[0], x[1] + size[1]], layer=layer, width=width)) THTQuartz(model, [x[0] + (size[0] - inner_size[0]) / 2, x[1] + (size[1] - inner_size[1]) / 2], inner_size, layer, width) # draws a THT quartz footprint (HC49) # +----------------+ # / \ # \ / # +----------------+ def THTQuartz(model, x, size, layer, width): THTQuartzIncomplete(model, x, size, 180, layer, width) # draws a THT quartz footprint (HC49) # +----------------+ # / \ # \ / # +----------------+ def THTQuartzIncomplete(model, x, size, angle, layer, width): inner_size = size r = inner_size[1] / 2 xtl = [x[0] + size[0] / 2 - (inner_size[0] / 2 - r), x[1] + size[1] / 2 - inner_size[1] / 2] xtr = [x[0] + size[0] / 2 + (inner_size[0] / 2 - r), x[1] + size[1] / 2 - inner_size[1] / 2] xbl = [x[0] + size[0] / 2 - (inner_size[0] / 2 - r), x[1] + size[1] / 2 + inner_size[1] / 2] xbr = [x[0] + size[0] / 2 + (inner_size[0] / 2 - r), x[1] + size[1] / 2 + inner_size[1] / 2] cl = [x[0] + size[0] / 2 - (inner_size[0] / 2 - r), x[1] + size[1] / 2] cr = [x[0] + size[0] / 2 + (inner_size[0] / 2 - r), x[1] + size[1] / 2] model.append(Line(start=xtl, end=xtr, layer=layer, width=width)) model.append(Line(start=xbl, end=xbr, layer=layer, width=width)) if angle >= 180: model.append(Arc(center=cl, start=xtl, angle=-angle, layer=layer, width=width)) model.append(Arc(center=cr, start=xtr, angle=angle, layer=layer, width=width)) else: model.append(Arc(center=cl, start=xtl, angle=-angle, layer=layer, width=width)) model.append(Arc(center=cr, start=xtr, angle=angle, layer=layer, width=width)) model.append(Arc(center=cl, start=xbl, angle=angle, layer=layer, width=width)) model.append(Arc(center=cr, start=xbr, angle=-angle, layer=layer, width=width)) # # This is an alternative to using silk keepout areas for simple cases. # It calculates a new endpoint for a horizontal or vertical line such that # the silk line has the correct minimal clearance. If the line is to short # given the default clearance, the clearance is reduced and new points are # calculated. # # Parameters: # - pad_size, pad_position, and pad_radius are the dimensions of the reference pad. # (pad that is expected to be intersected by the line) # - fixed_point: The fixed reference point # - moving_point: The point that will be moved (toward the fixed point) # if the line intersects the pads clearance area. # - silk_pad_offset: offset between edge of the pad and silk line center. # - min_lenght: minimum silk line length # # Returns a new point along the line or None if no valid point could be found # def nearestSilkPointOnOrthogonalLineSmallClerance(pad_size, pad_position, pad_radius, fixed_point, moving_point, silk_pad_offset_default, silk_pad_offset_reduced, min_lenght): if silk_pad_offset_reduced < silk_pad_offset_default: offset = (silk_pad_offset_default, silk_pad_offset_reduced) else: offset = (silk_pad_offset_default) for silk_pad_offset in (silk_pad_offset_default, silk_pad_offset_reduced): point = nearestSilkPointOnOrthogonalLine( pad_size, pad_position, pad_radius, fixed_point, moving_point, silk_pad_offset, min_lenght) if point is not None: return point return None # # This is an alternative to using silk keepout areas for simple cases. # It calculates a new endpoint for a horizontal or vertical line such that # the silk line has the correct minimal clearance. # # Parameters: # - pad_size, pad_position, and pad_radius are the dimensions of the reference pad. # (pad that is expected to be intersected by the line) # - fixed_point: The fixed reference point # - moving_point: The point that will be moved (toward the fixed point) # if the line intersects the pads clearance area. # - silk_pad_offset: offset between edge of the pad and silk line center. # - min_lenght: minimum silk line length # # Returns a new point along the line or None if no valid point could be found # def nearestSilkPointOnOrthogonalLine(pad_size, pad_position, pad_radius, fixed_point, moving_point, silk_pad_offset, min_lenght): if fixed_point[0] == moving_point[0]: normal_dir_idx = 0 elif fixed_point[1] == moving_point[1]: normal_dir_idx = 1 else: raise ValueError("nearestSilkPointOnOrthogonalLine only works for horizontal or vertical lines. \n" "(Either x or y coordinate of the two reference points must be equal)") inline_dir_idx = (normal_dir_idx+1)%2 line_pad_offset = fixed_point[normal_dir_idx] - pad_position[normal_dir_idx] rc_normal_dir = pad_size[normal_dir_idx]/2-pad_radius sign = 1 if pad_position[inline_dir_idx] - fixed_point[inline_dir_idx] > 0 else -1 ep_new = Vector2D(moving_point) if rc_normal_dir < line_pad_offset: # the silk outline is in the area where the radius of the pad is. dr_normal_dir = line_pad_offset - rc_normal_dir r = pad_radius + silk_pad_offset # rounding to avoid floating point errors if round(dr_normal_dir, 6) >= round(r, 6): return moving_point dr_inline = sqrt(r**2 - dr_normal_dir**2) ep_new[inline_dir_idx] = pad_position[inline_dir_idx] -\ sign*(pad_size[inline_dir_idx]/2 - (pad_radius-dr_inline)) else: ep_new[inline_dir_idx] = pad_position[inline_dir_idx] -\ sign*(pad_size[inline_dir_idx]/2 + silk_pad_offset) if sign*(ep_new[inline_dir_idx] - fixed_point[inline_dir_idx]) < min_lenght: return None if abs(ep_new[inline_dir_idx] - fixed_point[inline_dir_idx]) > math.fabs(moving_point[inline_dir_idx] - fixed_point[inline_dir_idx]): return moving_point return ep_new ================================================ FILE: scripts/tools/footprint_global_properties.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * crt_offset = 0.25 lw_fab = 0.1 lw_crt = 0.05 lw_slk = 0.12 slk_offset = lw_slk/2 slk_pad_offset = lw_slk/2+0.2 txt_offset = 1 grid_crt=0.01 min_pad_distance=0.2 fab_text_size_min=0.25 fab_text_size_max=2.00 ================================================ FILE: scripts/tools/footprint_keepout_area.py ================================================ # Kicad currently does not support adding keepout zones directly to footprints # For this reason the library maintainance team decided to communicate keepouts as follows: # - A polygone outlining the keepout area (on layer Dwgs.User) # - Hatching of this area on the same layer # - Text on Cmts.User: KEEPOUT (with additional information if necessary) import sys, os sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from math import sqrt KEEPOUT_DEFAULT_CONFIG={ 'graphical_layer':'Dwgs.User', 'line_width': 0.1, 'hatching_spacing': 2, 'text':{ 'size':[1,1], 'fontwidth':0.15, 'position':'center', 'layer':'Cmts.User' } } def addRectangularKeepout(kicad_mod, center, size, text='KEEPOUT', config=KEEPOUT_DEFAULT_CONFIG): keepout_edges={ 'left': center[0] - (size[0] / 2), 'top': center[1] - (size[1] / 2) } keepout_edges['right'] = keepout_edges['left'] + size[0] keepout_edges['bottom'] = keepout_edges['top'] + size[1] kicad_mod.append(RectLine( start=[keepout_edges['left'], keepout_edges['top']], end=[keepout_edges['right'], keepout_edges['bottom']], layer=config['graphical_layer'], width=config['line_width'])) if size[0] >= size[1]: rot = 0 longer_size = size[0] else: longer_size = size[1] rot = 90 fs = round(longer_size/len(text), 2) if fs > config['text']['size'][0]: size = config['text']['size'] thickness = config['text']['fontwidth'] else: size = [fs, fs] thickness = config['text']['fontwidth'] * fs kicad_mod.append(Text(type='user', text=text, at=center, rotation=rot, layer=config['text']['layer'], size=size, thickness=thickness)) p1 = {'x':keepout_edges['left'], 'y':keepout_edges['top']} p2 = {'x':keepout_edges['left'], 'y':keepout_edges['top']} # 45° hatching step = config['hatching_spacing'] step_x = step/sqrt(2) step_y = step_x p1_direction = 'move_right' p2_direction = 'move_down' while (1): if p1_direction == 'move_right': p1['x'] += step_x if p1['x'] > keepout_edges['right']: p1_direction = 'move_down' dx = keepout_edges['right'] - (p1['x'] - step_x) dy = step_y - dx p1['x'] = keepout_edges['right'] p1['y'] += dy else: p1['y'] += step_y if p2_direction == 'move_down': p2['y'] += step_y if p2['y'] > keepout_edges['bottom']: p2_direction = 'move_right' dy = keepout_edges['bottom'] - (p2['y'] - step_y) dx = step_x - dy p2['x'] += dx p2['y'] = keepout_edges['bottom'] else: p2['x'] += step_x if p1['y'] > keepout_edges['bottom']: return kicad_mod.append(Line(start=p1, end=p2, layer=config['graphical_layer'], width=config['line_width'])) ================================================ FILE: scripts/tools/footprint_scripts_DIP.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * # NOQA # overlen_top overlen_bottom # <---> <------> # O O O O ^ # | | | | | # +--------------------------------------------+ ^ | # | | | | # +--+ | | | # | | package_width | # +--+ | | pinrow_distance # | | | | # +--------------------------------------------+ v | # | | | | | # O O O O v # # <----RM----> def makeDIP(pins, rm, pinrow_distance_in, package_width, overlen_top, overlen_bottom, ddrill, pad, smd_pads=False, socket_width=0, socket_height=0, socket_pinrow_distance_offset=0, tags_additional=[], lib_name="Package_DIP", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], DIPName='DIP', DIPDescription='though-hole mounted DIP', DIPTags='THT DIP DIL PDIP', prefix_name = "", skip_pin = [], skip_count = False, right_cnt_start = -1): pinrow_distance = pinrow_distance_in + socket_pinrow_distance_offset h_fab = (pins / 2 - 1) * rm + overlen_top + overlen_bottom w_fab = package_width l_fab = (pinrow_distance - w_fab) / 2 t_fab = -overlen_top hasSocket = False if (socket_height > 0 and socket_width > 0): hasSocket = True h_fabs = socket_height w_fabs = socket_width l_fabs = (w_fabs - pinrow_distance) / 2 t_fabs = (h_fabs - (pins / 2 - 1) * rm) / 2 h_slk = h_fab + 2 * slk_offset w_slk = min(w_fab + 2 * slk_offset, pinrow_distance - pad[0] - 12 * slk_offset) l_slk = (pinrow_distance - w_slk) / 2 t_slk = -overlen_top - slk_offset w_crt = max(package_width, pinrow_distance + pad[0]) + 2 * crt_offset h_crt = max(h_fab, (pins / 2 - 1) * rm + pad[1]) + 2 * crt_offset hasSocket = False if (socket_height > 0 and socket_width > 0): hasSocket = True h_fabs = max(socket_height,h_slk) w_fabs = socket_width l_fabs = (pinrow_distance - w_fabs) / 2 t_fabs = ((pins / 2 - 1) * rm - h_fabs) / 2 h_slks = h_fabs + 2 * slk_offset w_slks = max(w_fabs, pinrow_distance + pad[0] + 6 * slk_offset) + 2 * slk_offset l_slks = (pinrow_distance - w_slks) / 2 t_slks = ((pins / 2 - 1) * rm - h_slks) / 2 w_crt = max(w_crt, w_fabs + 2 * crt_offset) h_crt = max(h_crt, h_fabs + 2 * crt_offset) l_crt = pinrow_distance / 2 - w_crt / 2 t_crt = (pins / 2 - 1) * rm / 2 - h_crt / 2 footprint_name = DIPName+"-{0}_W{1}mm".format(pins, round(pinrow_distance, 2)) if len(prefix_name) > 0: footprint_name = DIPName+'-'+prefix_name+"-{0}_W{1}mm".format(pins, round(pinrow_distance, 2)) description = "{0}-lead {3} package, row spacing {1} mm ({2} mils)".format(pins, round(pinrow_distance, 2), int(pinrow_distance / 2.54 * 100), DIPDescription) tags = DIPTags+" {0}mm {1}mm {2}mil".format(rm, pinrow_distance, int(pinrow_distance / 2.54 * 100)) if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset = [0, 0] if (smd_pads): offset = [-pinrow_distance / 2, -(pins / 2 - 1) * rm / 2] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) kicad_mod.setAttribute('smd') else: kicad_modg = kicad_mod # set general values kicad_modg.append( Text(type='reference', text='REF**', at=[pinrow_distance / 2, t_slk - txt_offset], layer='F.SilkS')) kicad_modg.append( Text(type='user', text='%R', at=[pinrow_distance/2, t_fab + h_fab / 2], layer='F.Fab')) kicad_modg.append( Text(type='value', text=footprint_name, at=[pinrow_distance / 2, t_slk + h_slk + txt_offset], layer='F.Fab')) # create FAB-layer bevelRectTL(kicad_modg, [l_fab, t_fab], [w_fab, h_fab], 'F.Fab', lw_fab) if hasSocket: kicad_modg.append( RectLine(start=[l_fabs, t_fabs], end=[l_fabs + w_fabs, t_fabs + h_fabs], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer DIPRectT(kicad_modg, [l_slk, t_slk], [w_slk, h_slk], 'F.SilkS', lw_slk) if hasSocket: # if smd_pads: # kicad_modg.append(Line(start=[l_slks, t_slks], end=[l_slks + w_slks, t_slks], layer='F.SilkS',width=lw_slk)) # kicad_modg.append(Line(start=[l_slks, t_slks+h_slks], end=[l_slks + w_slks, t_slks+h_slks], layer='F.SilkS',width=lw_slk)) # else: # kicad_modg.append(RectLine(start=[l_slks, t_slks], end=[l_slks+w_slks, t_slks+h_slks], layer='F.SilkS', width=lw_slk)) kicad_modg.append( RectLine(start=[l_slks, t_slks], end=[l_slks + w_slks, t_slks + h_slks], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads p1 = int(1) x1 = 0 y1 = 0 p2 = int(pins / 2 + 1) if right_cnt_start >= 0: # The pins on the right side shall start with a specific value p2 = right_cnt_start x2 = pinrow_distance y2 = (pins / 2 - 1) * rm if smd_pads: pad_type = Pad.TYPE_SMT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_RECT pad_layers = ['F.Cu', 'F.Mask', 'F.Paste'] else: pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_OVAL pad_layers = ['*.Cu', '*.Mask'] for p in range(1, int(pins / 2 + 1)): addpinL = True for sp in skip_pin: if sp == p: # The pin number is among those who should not be added addpinL = False if addpinL: if p == 1: kicad_modg.append(Pad(number=p1, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) else: kicad_modg.append(Pad(number=p1, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) addpinR = True for sp in skip_pin: if sp == p + int(pins / 2): # The pin number is among those who should not be added addpinR = False if addpinR: kicad_modg.append(Pad(number=p2, type=pad_type, shape=pad_shapeother, at=[x2, y2], size=pad, drill=ddrill, layers=pad_layers)) # Do not increase the pin number if it should be skipped if not (skip_count and not addpinL): p1 = p1 + 1 # Do not increase the pin number if it should be skipped if not (skip_count and not addpinR): p2 = p2 + 1 y1 = y1 + rm y2 = y2 - rm # add model kicad_modg.append( Model(filename="${KISYS3DMOD}/" + lib_name + ".3dshapes/" + footprint_name + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # overlen_top overlen_bottom # <---> <------> # O O O O ^ # | | | | | # +--------------------------------------------+ ^ | # | +---+ ^ | | | # | | | | | | | # | +---+ switch_width | package_width | # | | | | | | pinrow_distance # | +---+ v | | | # +--------------------------------------------+ v | # | | | | | # O O O O v # <--->switch_height # <----RM----> # # mode=Piano/Slide # def makeDIPSwitch(pins, rm, pinrow_distance, package_width, overlen_top, overlen_bottom, ddrill, pad, switch_width, switch_height, mode='Piano', smd_pads=False, tags_additional=[], lib_name="Button_Switch_THT", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 90], specialFPName="", SOICStyleSilk=False, cornerPads=[], cornerPadOffsetX=0, cornerPadOffsetY=0, webpage="", device_name="", switchtype="SPST"): switches = int(pins / 2) h_fab = (pins / 2 - 1) * rm + overlen_top + overlen_bottom w_fab = package_width l_fab = (pinrow_distance - w_fab) / 2 t_fab = -overlen_top h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset #if (package_width > pinrow_distance): # w_slk = max(w_fab + 2 * slk_offset, pinrow_distance + pad[0] + 2 * slk_offset) #else: # w_slk = min(w_fab + 2 * slk_offset, pinrow_distance - pad[0] - 4 * slk_offset) l_slk = (pinrow_distance - w_slk) / 2 t_slk = -overlen_top - slk_offset if len(cornerPads) == 2: t_slk = t_fab + cornerPadOffsetY - cornerPads[1] / 2 - slk_offset h_slk = t_fab + h_fab - cornerPadOffsetY + cornerPads[1] / 2 + slk_offset - t_slk w_crt = max(package_width, pinrow_distance + pad[0]) + 2 * crt_offset h_crt = max(h_fab, (pins / 2 - 1) * rm + pad[1], h_slk) + 2 * crt_offset l_crt = pinrow_distance / 2 - w_crt / 2 t_crt = min(t_slk - crt_offset, (pins / 2 - 1) * rm / 2 - h_crt / 2) if (mode == 'Piano'): l_crt = l_crt - switch_width w_crt = w_crt + switch_width smdtext='' smddescription='' if smd_pads: #smdtext='_SMD'; smddescription='SMD ' add_type="" bodysize="{0}x{1}mm".format(round(package_width,2), round(overlen_top+overlen_bottom+(pins/2-1)*rm,2)) if len(device_name)>0: add_type="_"+device_name bodysize="" bodysizefp=""; if len(bodysize)>0: bodysizefp=bodysize+"_" footprint_name = "SW_DIP_{6}x{0:02}_{4}{5}_{7}W{1}mm_P{2}mm{3}".format(switches, round(pinrow_distance, 2), round(rm, 2), smdtext, mode,add_type,switchtype,bodysizefp) description = "{4}{0}x-dip-switch {6} {5}, {3}, row spacing {1} mm ({2} mils), body size {7}".format(switches, round(pinrow_distance, 2), int(pinrow_distance / 2.54 * 100), mode,smddescription,device_name,switchtype,bodysize) if len(webpage)>0: description=description+" (see "+webpage+")" tags = "{3}DIP Switch {4} {0} {1}mm {2}mil".format(mode, pinrow_distance, int(pinrow_distance / 2.54 * 100),smddescription,switchtype) if (len(tags_additional) > 0): for t in tags_additional: if t != "SMD": # suppress "SMD" in file name since this is already part of folder name footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t if len(specialFPName) > 0: footprint_name = specialFPName print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset = [0, 0] if (smd_pads): offset = [-pinrow_distance / 2, -(pins / 2 - 1) * rm / 2] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) kicad_mod.setAttribute('smd') else: kicad_modg = kicad_mod # add texts if pins == 2: fab_ref_size = [0.6, 0.6] else: ss=max(0.25, min((package_width-switch_width)*0.35, 0.8)) fab_ref_size = [ss, ss] kicad_modg.append(Text(type='reference', text='REF**', at=[pinrow_distance / 2, t_slk - txt_offset], layer='F.SilkS')) kicad_modg.append(Text(type='value', text=footprint_name, at=[pinrow_distance / 2, t_slk + h_slk + txt_offset], layer='F.Fab')) if (mode == 'Piano'): kicad_modg.append(Text(type='user', text='%R', at=[pinrow_distance/2, t_fab + h_fab /2], size=fab_ref_size, layer='F.Fab', thickness=fab_ref_size[0]*0.15)) else: kicad_modg.append(Text(type='user', text='%R', at=[pinrow_distance/2 + (package_width+switch_width)/4, t_fab + h_fab /2], rotation=90, size=fab_ref_size, layer='F.Fab', thickness=fab_ref_size[0]*0.15)) kicad_modg.append(Text(type='user', text='on', at=[pinrow_distance/2 + (package_width+switch_width)/4-pinrow_distance/4, t_fab + (overlen_top-switch_height/2)/2], rotation=0, size=fab_ref_size, layer='F.Fab', thickness=fab_ref_size[0]*0.15)) # create pads p1 = int(1) x1 = 0 y1 = 0 p2 = int(pins / 2 + 1) x2 = pinrow_distance y2 = (pins / 2 - 1) * rm keepouts=[]; if smd_pads: pad_type = Pad.TYPE_SMT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_RECT pad_layers = ['F.Cu', 'F.Mask', 'F.Paste'] else: pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_OVAL pad_layers = ['*.Cu', '*.Mask'] keepout_addsize=4*max(slk_offset, lw_slk) for p in range(1, int(pins / 2 + 1)): if p == 1: kicad_modg.append(Pad(number=p1, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+keepout_addsize, pad[1]+keepout_addsize) else: kicad_modg.append(Pad(number=p1, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x1, y1, pad[0]+keepout_addsize, pad[1]+keepout_addsize) kicad_modg.append(Pad(number=p2, type=pad_type, shape=pad_shapeother, at=[x2, y2], size=pad, drill=ddrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x2, y2, pad[0]+keepout_addsize, pad[1]+keepout_addsize) p1 = p1 + 1 p2 = p2 + 1 y1 = y1 + rm y2 = y2 - rm if len(cornerPads) == 2: kicad_modg.append(Pad(number=pins + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[l_fab + cornerPadOffsetX, t_fab + cornerPadOffsetY], size=cornerPads, drill=0, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(l_fab + cornerPadOffsetX, t_fab + cornerPadOffsetY, cornerPads[0]+keepout_addsize, cornerPads[1]+keepout_addsize) kicad_modg.append(Pad(number=pins + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[l_fab + w_fab - cornerPadOffsetX, t_fab + cornerPadOffsetY], size=cornerPads, drill=0, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(l_fab + w_fab - cornerPadOffsetX, t_fab + cornerPadOffsetY, cornerPads[0]+keepout_addsize, cornerPads[1]+keepout_addsize) kicad_modg.append(Pad(number=pins + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[l_fab + cornerPadOffsetX, t_fab + h_fab - cornerPadOffsetY], size=cornerPads, drill=0, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(l_fab + cornerPadOffsetX, t_fab + h_fab - cornerPadOffsetY, cornerPads[0]+keepout_addsize, cornerPads[1]+keepout_addsize) kicad_modg.append(Pad(number=pins + 1, type=Pad.TYPE_SMT, shape=Pad.SHAPE_RECT, at=[l_fab + w_fab - cornerPadOffsetX, t_fab + h_fab - cornerPadOffsetY], size=cornerPads, drill=0, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(l_fab + w_fab - cornerPadOffsetX, t_fab + h_fab - cornerPadOffsetY, cornerPads[0]+keepout_addsize, cornerPads[1]+keepout_addsize) # create FAB-layer bevelRectTL(kicad_modg, [l_fab, t_fab], [w_fab, h_fab], 'F.Fab', lw_fab) for sw in range(0, switches): x = pinrow_distance / 2 y = sw * rm if (mode == 'Piano'): kicad_modg.append( RectLine(start=[l_fab, y - switch_height / 2], end=[l_fab - switch_width, y + switch_height / 2], layer='F.Fab', width=lw_fab)) else: kicad_modg.append(RectLine(start=[x - switch_width / 2, y - switch_height / 2], end=[x + switch_width / 2, y + switch_height / 2], layer='F.Fab', width=lw_fab)) kicad_modg.append(RectFill(start=[x - switch_width / 2, y - switch_height / 2], end=[x - switch_width / 6, y + switch_height / 2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[x - switch_width / 6, y - switch_height / 2], end=[x - switch_width / 6, y + switch_height / 2], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer if SOICStyleSilk and smd_pads: addHLineWithKeepout(kicad_modg, l_fab-slk_offset, l_fab + w_fab+slk_offset, t_slk + h_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts) if (overlen_top>0.5): addHLineWithKeepout(kicad_modg,-pad[0] / 2, l_fab-slk_offset, -pad[1] / 2-lw_slk-3*slk_offset, layer='F.SilkS', width=lw_slk, keepouts=keepouts) addVLineWithKeepout(kicad_modg, l_fab-slk_offset, t_slk, -pad[1] / 2-lw_slk-3*slk_offset, layer='F.SilkS', width=lw_slk, keepouts=keepouts) addHLineWithKeepout(kicad_modg, l_fab-slk_offset, l_fab + w_fab+slk_offset, t_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts) addVLineWithKeepout(kicad_modg, l_fab + w_fab+slk_offset, t_slk, t_slk+overlen_top, layer='F.SilkS', width=lw_slk, keepouts=keepouts) else: addHLineWithKeepout(kicad_modg, -pad[0] / 2, l_fab + w_fab+slk_offset, t_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts) if overlen_bottom>0.5: addVLineWithKeepout(kicad_modg, l_fab -slk_offset, t_slk+h_slk, t_slk+h_slk-overlen_bottom, layer='F.SilkS', width=lw_slk, keepouts=keepouts) addVLineWithKeepout(kicad_modg, l_fab + w_fab+slk_offset, t_slk+h_slk, t_slk+h_slk-overlen_bottom, layer='F.SilkS', width=lw_slk, keepouts=keepouts) else: addRectAndTLMarkWithKeepout(kicad_modg, l_slk, t_slk, w_slk, h_slk, min(max(0.5, pad[0]), rm*0.45), layer='F.SilkS', width=lw_slk, keepouts=keepouts) for sw in range(0, switches): x = pinrow_distance / 2 y = sw * rm if (mode == 'Piano'): addRectWithKeepout(kicad_modg, l_slk - switch_width - slk_offset, y - switch_height / 2 - slk_offset, switch_width + slk_offset, switch_height+2*slk_offset, layer='F.SilkS', width=lw_slk) else: kicad_modg.append(RectLine(start=[x - switch_width / 2, y - switch_height / 2], end=[x + switch_width / 2, y + switch_height / 2], layer='F.SilkS', width=lw_slk)) kicad_modg.append( RectFill(start=[x - switch_width / 2, y - switch_height / 2], end=[x - switch_width / 6, y + switch_height / 2], layer='F.SilkS', width=lw_slk)) kicad_modg.append( Line(start=[x - switch_width / 6, y - switch_height / 2], end=[x - switch_width / 6, y + switch_height / 2], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # add model kicad_modg.append( Model(filename="${KISYS3DMOD}/" + lib_name + ".3dshapes/" + footprint_name + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') ================================================ FILE: scripts/tools/footprint_scripts_LEDs.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_global_properties import * # LED footprints # style options: # 1. type="box" # +----------------+ ^ # | | | # | OO OO | h # | | | # +----------------+ v # <---rm---> # <-------w--------> # 2. type="round" # /----------\ ^ # | \ | # | OO OO | h # | / | # \__________/ v # <-rm-> # <-------w--------> # 3. type="roundedbox" # +--------------\ ^ # | \ | # | OO OO | h # | / | # +--------------/ v # <---rm---> # <-------w--------> # 4. type="oval" # +----------------+ ^ # | | | # | OO OO | h # | | | # +----------------+ v # <---rm---> # <-------w--------> # 2. type="round_simple" # /----------\ ^ # / \ | # | OO OO | h # \ / | # \__________/ v # <-rm-> # <-------w--------> # in the center a second circle is drawn if rin>0 def makeLEDRadial(rm, w, h, ddrill, win=0, rin=0, pins=2, type="round", x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=[], add_description="", classname="LED", lib_name="LEDs", name_additions=[], script3d="", height3d=8, height3d_bottom=1): padx = 2 * ddrill pady = padx if padx + min_pad_distance > rm: padx = (rm - min_pad_distance) txtoffset = txt_offset pad1style = Pad.SHAPE_RECT padpos = [] offset = [0, 0] overpad_width = (pins - 1) * rm xpad = -overpad_width / 2 offset = [-xpad, 0] for p in range(1, pins + 1): padpos.append([p, xpad, 0, ddrill, padx, pady]) xpad = xpad + rm l_fab = -w / 2 t_fab = -h / 2 w_fab = w h_fab = h d_fab = max(w, h) d2_fab = rin h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset d_slk = d_fab + lw_slk + slk_offset w_crt = max(w_slk, overpad_width + padx) + 2 * crt_offset h_crt = max(h_slk, pady) + 2 * crt_offset l_crt = -w_crt / 2 t_crt = -h_crt / 2 snfp = "" sn = "" snt = "" fnsize = "" sizetag = "" if type == "round" or type == "round_simple": fnsize = "_D{0:0.1f}mm".format(rin) sizetag = "diameter {0:0.1f}mm".format(rin) else: if type == "oval": sizetag = " Oval" if type == "box": sizetag = " Rectangular" wsize = w if type == "box" and win > 0: wsize = win fnsize = fnsize + "_W{0:0.1f}mm_H{1:0.1f}mm".format(wsize, h) sizetag = sizetag + " size {0:0.1f}x{1:0.1f}mm^2".format(wsize, h) if rin > 0: fnsize = "_D{0:0.1f}mm".format(rin) + fnsize sizetag = sizetag + " diameter {0:0.1f}mm".format(rin) fnpincnt = "" pincnttag = "{0:d} pins".format(pins) if pins > 2: fnpincnt = "-{0:d}".format(pins) if type == "box": fnpincnt = fnpincnt + "pins" footprint_name = classname + fnsize + fnpincnt description = classname tags = classname addedtags = specialtags if len(sizetag) > 0: addedtags.append(sizetag) if len(pincnttag) > 0: addedtags.append(pincnttag) for t in addedtags: description = description + ", " + t tags = tags + " " + t if (specialfpname != ""): footprint_name = specialfpname; if len(add_description) > 0: description = description + ", " + add_description for n in name_additions: if len(n) > 0: footprint_name = footprint_name + "_" + n print(footprint_name) if script3d != "": with open(script3d, "a") as myfile: myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '0.02')\n") myfile.write("App.ActiveDocument.recompute()\n") myfile.write("# rin\nApp.ActiveDocument.Spreadsheet.set('B1', '{0}')\n".format(rin)) myfile.write("# w\nApp.ActiveDocument.Spreadsheet.set('B2', '{0}')\n".format(w)) myfile.write("# h\nApp.ActiveDocument.Spreadsheet.set('C2', '{0}')\n".format(h)) myfile.write("# RM\nApp.ActiveDocument.Spreadsheet.set('B3', '{0}')\n".format(rm)) myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '{0}')\n".format(ddrill - 0.3)) myfile.write("# H\nApp.ActiveDocument.Spreadsheet.set('B5', '{0}')\n".format(height3d)) myfile.write("# H_bottom\nApp.ActiveDocument.Spreadsheet.set('B6', '{0}')\n".format(height3d_bottom)) myfile.write("App.ActiveDocument.recompute()\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format( footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[0, t_slk - txtoffset], layer='F.SilkS')) kicad_modg.append(Text(type='value', text=footprint_name, at=[0, t_slk + h_slk + txtoffset], layer='F.Fab')) # create FAB-layer if type == "round": kicad_modg.append(Circle(center=[0, 0], radius=d2_fab / 2, layer='F.Fab', width=lw_fab)) xmark = d2_fab / 2 ymark = math.sqrt(d_fab * d_fab / 4 - xmark * xmark) alpha = 360 - 2 * math.atan(ymark / xmark) / 3.1415 * 180 kicad_modg.append(Arc(center=[0, 0], start=[-xmark, -ymark], angle=alpha, layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-xmark, -ymark], end=[-xmark, ymark], angle=alpha, layer='F.Fab', width=lw_fab)) if type == "round_simple": kicad_modg.append(Circle(center=[0, 0], radius=d2_fab / 2, layer='F.Fab', width=lw_fab)) kicad_modg.append(Circle(center=[0, 0], radius=d_fab / 2, layer='F.Fab', width=lw_fab)) elif type == "box": kicad_modg.append( RectLine(start=[l_fab, t_fab], end=[l_fab + w_fab, t_fab + h_fab], layer='F.Fab', width=lw_fab)) if d2_fab > 0: kicad_modg.append(Circle(center=[0, 0], radius=d2_fab / 2, layer='F.Fab', width=lw_fab)) if win > 0: kicad_modg.append( RectLine(start=[-win / 2, t_fab], end=[win / 2, t_fab + h_fab], layer='F.Fab', width=lw_fab)) elif type == "oval": r = w / 2 ystart = 0 xstart = math.sqrt(r * r - ystart * ystart) ycenter = h / 2 - r alpha = 180 - 2 * math.atan(math.fabs(ycenter) / xstart) / 3.1415 * 180 kicad_modg.append(Arc(center=[0, -ycenter], start=[-xstart, ystart], angle=alpha, layer='F.Fab', width=lw_fab)) kicad_modg.append(Arc(center=[0, ycenter], start=[-xstart, -ystart], angle=-alpha, layer='F.Fab', width=lw_fab)) # build keepeout for SilkScreen keepouts = [] for p in padpos: if p[0] == 1: keepouts = keepouts + addKeepoutRect(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) else: keepouts = keepouts + addKeepoutRound(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) # create SILKSCREEN-layer if type == "box": addRectWithKeepout(kicad_modg, l_slk, t_slk, w_slk, h_slk, 'F.SilkS', lw_slk, keepouts) if pins == 3: addVLineWithKeepout(kicad_modg, -offset[0] + rm / 2, t_slk, t_slk + h_slk, 'F.SilkS', lw_slk, keepouts) else: addVLineWithKeepout(kicad_modg, l_slk + lw_slk, t_slk, t_slk + h_slk, 'F.SilkS', lw_slk, keepouts) addVLineWithKeepout(kicad_modg, l_slk + 2 * lw_slk, t_slk, t_slk + h_slk, 'F.SilkS', lw_slk, keepouts) elif type == "round": xmark = d2_fab / 2 + slk_offset ymark = math.sqrt(d_slk * d_slk / 4 - xmark * xmark) ypad = pady / 2 + slk_offset + lw_slk xpad = math.sqrt(d_slk * d_slk / 4 - ypad * ypad) alphamark = math.atan(ymark / xmark) / 3.1415 * 180 alphapad = math.atan(ypad / xpad) / 3.1415 * 180 alpha = 180 - alphamark if containedInAnyKeepout(xmark, 0.1, keepouts) or containedInAnyKeepout(d_fab / 2, 0.1, keepouts): alpha = alpha - alphapad kicad_modg.append(Arc(center=[0, 0], start=[-xmark, -ymark], angle=alpha, layer='F.SilkS', width=lw_slk)) kicad_modg.append(Arc(center=[0, 0], start=[-xmark, ymark], angle=-alpha, layer='F.SilkS', width=lw_slk)) addVLineWithKeepout(kicad_modg, -xmark, -ymark, ymark, 'F.SilkS', lw_slk, keepouts) ypad = pady / 2 + slk_offset + lw_slk xpad = math.sqrt(d2_fab * d2_fab / 4 - ypad * ypad) alphapad = math.atan(ypad / xpad) / 3.1415 * 180 alpha = 180 if containedInAnyKeepout(d2_fab / 2, 0.1, keepouts) or containedInAnyKeepout(-d2_fab / 2, 0.1, keepouts): alpha = alpha - 2 * alphapad if alpha == 180: kicad_modg.append(Circle(center=[0, 0], radius=d2_fab / 2, layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(Arc(center=[0, 0], start=[-xpad, -ypad], angle=alpha, layer='F.SilkS', width=lw_slk)) kicad_modg.append(Arc(center=[0, 0], start=[-xpad, ypad], angle=-alpha, layer='F.SilkS', width=lw_slk)) elif type == "round_simple": rs = [d2_fab, d_slk] xpads = [] ypads = [] fullCircle = False for r in rs: ypad = pady / 2 + slk_offset + lw_slk xpad = math.sqrt(r * r / 4 - ypad * ypad) xpads.append(xpad) ypads.append(ypad) alphapad = math.atan(ypad / xpad) / 3.1415 * 180 alpha = 180 if containedInAnyKeepout(r / 2, 0.1, keepouts) or containedInAnyKeepout(-r / 2, 0.1, keepouts): alpha = alpha - 2 * alphapad if alpha == 180: kicad_modg.append(Circle(center=[0, 0], radius=r / 2, layer='F.SilkS', width=lw_slk)) fullCircle = True else: kicad_modg.append(Arc(center=[0, 0], start=[-xpad, -ypad], angle=alpha, layer='F.SilkS', width=lw_slk)) kicad_modg.append(Arc(center=[0, 0], start=[-xpad, ypad], angle=-alpha, layer='F.SilkS', width=lw_slk)) if fullCircle: x = -d_slk / 2 + lw_slk * 2 y = math.sqrt(d_slk * d_slk / 4 - x * x) kicad_modg.append(Line(start=[x, -y], end=[x, y], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append( Line(start=[-xpads[0], ypads[0]], end=[-xpads[1], ypads[0]], layer='F.SilkS', width=lw_slk)) kicad_modg.append( Line(start=[-xpads[0], -ypads[0]], end=[-xpads[1], -ypads[0]], layer='F.SilkS', width=lw_slk)) elif type == "oval": r = w_slk / 2 ystart = 0 xstart = math.sqrt(r * r - ystart * ystart) ycenter = h_slk / 2 - r alpha = 180 - 2 * math.atan(math.fabs(ycenter) / xstart) / 3.1415 * 180 kicad_modg.append( Arc(center=[0, -ycenter], start=[-xstart, ystart], angle=alpha, layer='F.SilkS', width=lw_slk)) kicad_modg.append( Arc(center=[0, ycenter], start=[-xstart, -ystart], angle=-alpha, layer='F.SilkS', width=lw_slk)) xmark = -xstart + 2 * lw_slk ymark = ycenter + math.sqrt(r * r - xmark * xmark) print(ymark, ycenter, ymark + ycenter) addVLineWithKeepout(kicad_modg, xmark, -ymark, ymark, 'F.SilkS', lw_slk, keepouts) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + w_crt + offset[0]), roundCrt(t_crt + h_crt + offset[1])], layer='F.CrtYd', width=lw_crt)) # debug_draw_keepouts(kicad_modg, keepouts) # create pads pn = 1 for p in padpos: ps = Pad.SHAPE_CIRCLE if (p[4] != p[5]): ps = Pad.SHAPE_OVAL if p[0] == 1: ps = pad1style kicad_modg.append(Pad(number=p[0], type=Pad.TYPE_THT, shape=ps, at=[p[1], p[2]], size=[p[4], p[5]], drill=p[3], layers=['*.Cu', '*.Mask'])) # add model if (has3d != 0): kicad_modg.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=[0, 0, 0])) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # LED footprints for horizontally mounted LEDs # style options: # 1. type="simple" # +------\ ^ # ^ OO | \ | # rm | | dled # v OO | / | # +------/ v # <------>offsetled # <--wled-> # # type="round"/"rect" def makeLEDHorizontal(pins=2,rm=2.544,dled=5,dledout=5.8,offsetled=2.54,wled=8.6, ddrill=0.8, wledback=1, type="round", x_3d=[0, 0, 0], s_3d=[1 / 2.54, 1 / 2.54, 1 / 2.54], has3d=1, specialfpname="", specialtags=[], add_description="", classname="LED", lib_name="LEDs", name_additions=[], script3d="", height3d=5, ledypos=0): padx = 2 * ddrill pady = padx if padx + min_pad_distance > rm: padx = (rm - min_pad_distance) txtoffset = txt_offset pad1style = Pad.SHAPE_RECT padpos = [] offset = [0, 0] overpad_width = (pins - 1) * rm xpad = -overpad_width / 2 offset = [-xpad, 0] for p in range(1, pins + 1): padpos.append([p, xpad, 0, ddrill, padx, pady]) xpad = xpad + rm l_fab = -max(dledout ,overpad_width+padx)/2 t_fab = -pady / 2 w_fab = max(dledout,overpad_width+padx) h_fab = pady/2+offsetled+wled h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset w_crt = max(w_slk, overpad_width + padx) + 2 * crt_offset h_crt = h_slk + 2 * crt_offset l_crt = l_slk-crt_offset t_crt = t_slk-crt_offset snfp = "" sn = "" snt = "" fnsize = "" sizetag = "" if type == "round": fnsize = "_D{0:0.1f}mm".format(dled) sizetag = "diameter {0:0.1f}mm".format(dled) else: if dled!=dledout: fnsize = fnsize + "_D{0:0.1f}mm".format(dled) sizetag = sizetag + " diameter {0:0.1f}mm".format(dled) else: sizetag = " Rectangular" fnsize = fnsize + "_W{0:0.1f}mm_H{1:0.1f}mm".format(dled, height3d) sizetag = sizetag + " size {0:0.1f}x{1:0.1f}mm^2".format(dled, height3d) fnypos="" if ledypos>0: fnypos = "_Z{0:0.1f}mm".format(ledypos) sizetag = sizetag+ " z-position of LED center {0:0.1f}mm".format(ledypos) else: ledypos=math.ceil(dled/2+0.5) fnpincnt = "" pincnttag = "{0:d} pins".format(pins) if pins > 2: fnpincnt = "-{0:d}pins".format(pins) footprint_name = classname + fnsize + fnpincnt description = classname tags = classname addedtags = specialtags if len(sizetag) > 0: addedtags.append(sizetag) if len(pincnttag) > 0: addedtags.append(pincnttag) for t in addedtags: description = description + ", " + t tags = tags + " " + t if (specialfpname != ""): footprint_name = specialfpname; if len(add_description) > 0: description = description + ", " + add_description for n in name_additions: if len(n) > 0: footprint_name = footprint_name + "_" + n footprint_name=footprint_name+"_Horizontal_O{0:1.2f}mm{1}".format(offsetled,fnypos) print(footprint_name) if script3d != "": with open(script3d, "a") as myfile: myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '0.02')\n") myfile.write("App.ActiveDocument.recompute()\n") myfile.write("# dled\nApp.ActiveDocument.Spreadsheet.set('B1', '{0}')\n".format(dled)) myfile.write("# dledout\nApp.ActiveDocument.Spreadsheet.set('B2', '{0}')\n".format(dledout)) myfile.write("# offsetled\nApp.ActiveDocument.Spreadsheet.set('B3', '{0}')\n".format(offsetled)) myfile.write("# RM\nApp.ActiveDocument.Spreadsheet.set('B4', '{0}')\n".format(rm)) myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B5', '{0}')\n".format(ddrill - 0.3)) myfile.write("# H\nApp.ActiveDocument.Spreadsheet.set('B6', '{0}')\n".format(height3d)) myfile.write("# wled\nApp.ActiveDocument.Spreadsheet.set('B7', '{0}')\n".format(wled)) myfile.write("# ledypos\nApp.ActiveDocument.Spreadsheet.set('B8', '{0}')\n".format(ledypos)) myfile.write("# wledback\nApp.ActiveDocument.Spreadsheet.set('B9', '{0}')\n".format(wledback)) myfile.write("App.ActiveDocument.recompute()\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format( footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[0, t_slk - txtoffset], layer='F.SilkS')) kicad_modg.append(Text(type='value', text=footprint_name, at=[0, t_slk + h_slk + txtoffset], layer='F.Fab')) # create FAB-layer if type == "round": kicad_modg.append(Arc(center=[0,offsetled+wled-dled/2], start=[-dled/2,offsetled+wled-dled/2], angle=-180 , layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[ -dled/2,offsetled], end=[-dled / 2,offsetled+wled-dled/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[dled / 2, offsetled], end=[dled / 2, offsetled + wled - dled / 2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[ -dled/2,offsetled], end=[dled / 2,offsetled], layer='F.Fab',width=lw_fab)) kicad_modg.append(RectLine(start=[ dledout/2,offsetled], end=[dled / 2,offsetled+wledback], layer='F.Fab',width=lw_fab)) elif type == "box": if wledback<=0: kicad_modg.append( RectLine(start=[-dledout / 2, offsetled], end=[dledout / 2, offsetled + wled], layer='F.Fab',width=lw_fab)) else: kicad_modg.append(RectLine(start=[-dledout / 2,offsetled], end=[dledout / 2,offsetled+wledback], layer='F.Fab',width=lw_fab)) if dled != dledout: kicad_modg.append( RectLine(start=[-dled / 2, offsetled+wledback], end=[dled / 2, offsetled + wled], layer='F.Fab',width=lw_fab)) for p in padpos: kicad_modg.append( RectLine(start=[p[1],p[2]], end=[p[1],offsetled], layer='F.Fab', width=lw_fab)) # build keepeout for SilkScreen keepouts = [] for p in padpos: if p[0] == 1: keepouts = keepouts + addKeepoutRect(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) else: keepouts = keepouts + addKeepoutRound(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) # create SILKSCREEN-layer if type == "round": kicad_modg.append(Arc(center=[0, offsetled + wled - dled/2], start=[-dled / 2-slk_offset, offsetled + wled - dled/2], angle=-180,layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[-dled / 2-slk_offset, offsetled-slk_offset], end=[-dled / 2-slk_offset, offsetled + wled - dled / 2], layer='F.SilkS',width=lw_slk)) kicad_modg.append(Line(start=[dled / 2+slk_offset, offsetled-slk_offset], end=[dled / 2+slk_offset, offsetled + wled - dled / 2], layer='F.SilkS',width=lw_slk)) kicad_modg.append(Line(start=[-dled / 2-slk_offset, offsetled-slk_offset], end=[dled / 2+slk_offset, offsetled-slk_offset], layer='F.SilkS', width=lw_slk)) kicad_modg.append(RectLine(start=[dledout / 2+slk_offset, offsetled-slk_offset], end=[dled / 2+slk_offset, offsetled + wledback+slk_offset], layer='F.SilkS',width=lw_slk)) elif type == "box": if wledback<=0: kicad_modg.append(RectLine(start=[-dledout / 2-slk_offset, offsetled-slk_offset], end=[dledout / 2+slk_offset, offsetled + wled+slk_offset], layer='F.SilkS',width=lw_slk)) kicad_modg.append(Line(start=[-dledout / 2 - slk_offset+lw_slk, offsetled - slk_offset],end=[-dledout / 2+lw_slk -slk_offset, offsetled + wled + slk_offset], layer='F.SilkS',width=lw_slk)) kicad_modg.append(Line(start=[-dledout / 2 - slk_offset+lw_slk*2, offsetled - slk_offset],end=[-dledout / 2+lw_slk*2 -slk_offset, offsetled + wled + slk_offset], layer='F.SilkS',width=lw_slk)) else: kicad_modg.append(RectLine(start=[-dledout / 2-slk_offset,offsetled-slk_offset], end=[dledout / 2+slk_offset,offsetled+wledback+slk_offset], layer='F.SilkS',width=lw_slk)) kicad_modg.append(Line(start=[-dledout / 2 - slk_offset+lw_slk, offsetled - slk_offset],end=[-dledout / 2 + lw_slk - slk_offset, offsetled + wledback + slk_offset],layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[-dledout / 2 - slk_offset+lw_slk*2, offsetled - slk_offset],end=[-dledout / 2 + lw_slk*2 - slk_offset, offsetled + wledback + slk_offset],layer='F.SilkS', width=lw_slk)) if dled != dledout: kicad_modg.append( RectLine(start=[-dled / 2-slk_offset, offsetled+wledback+slk_offset], end=[dled / 2+slk_offset, offsetled + wled+slk_offset], layer='F.SilkS',width=lw_slk)) for p in padpos: if pady/2+slk_offset+lw_slk pad_sep_x + pad[0]): hsfactorx = 1 hsfactory = 1.75 elif (pins == 4 and pack_width < pad_sep_x + pad[0] and pack_height < pad_sep_y + pad[1]): hsfactorx = 1.5 hsfactory = 1.5 elif (pins == 4 and pack_width > pad_sep_x + pad[0] and pack_height < pad_sep_y + pad[1]): hsfactorx = 1.1 hsfactory = 1.5 elif (pins == 4 and pack_width < pad_sep_x + pad[0] and pack_height > pad_sep_y + pad[1]): hsfactorx = 1.5 hsfactory = 1.1 makeSMDCrystal(footprint_name, addSizeFootprintName, pins, pad_sep_x + pad[0] * (hsfactorx - 1), pad_sep_y + pad[1] * (hsfactory - 1), [pad[0] * hsfactorx, pad[1] * hsfactory], pack_width, pack_height, pack_bevel, hasAdhesive, adhesivePos, adhesiveSize, style, description + ", hand-soldering", tags + " hand-soldering", lib_name, offset3d, scale3d, rotate3d, name_addition="_HandSoldering") # # <----------pad_sep_x-------------> # <----------pack_width--------------> # #=============# #=============# # | 4 | | 3 | # | +----------------------------------+ | ^ ^ # | | | | | | | | # #=============# #=============# | | # | | | | # | | pack_height | # | | | pad_sep_y # | | | | # #=============# #=============# | ^ | # | | | | | | | | | # | +----------------------------------+ | v | v # | 1 | | 2 | pad[1] # #=============# #=============# v # <---pad[0]----> # # # pins=2,4 # style="rect"/"hc49"/"dip" def makeSMDCrystal(footprint_name, addSizeFootprintName, pins, pad_sep_x, pad_sep_y, pad, pack_width, pack_height, pack_bevel, hasAdhesive=False, adhesivePos=[0, 0], adhesiveSize=1, style="rect", description="Crystal SMD SMT", tags=[], lib_name="Crystals", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], name_addition=""): fpname = footprint_name if addSizeFootprintName: fpname += "-{2}pin_{0:2.1f}x{1:2.1f}mm".format(pack_width, pack_height, pins) fpname = fpname + name_addition overpad_height = pad_sep_y + pad[1] overpad_width = pad_sep_x + pad[0] if pins == 3: overpad_height = pad_sep_y * 2 + pad[1] overpad_width = pad_sep_x * 2 + pad[0] betweenpads_x_slk = pad_sep_x - pad[0] - 2 * slk_offset betweenpads_y_slk = pad_sep_y - pad[1] - 2 * slk_offset overpads_x_slk = pad_sep_x + pad[0] + 2 * slk_offset overpads_y_slk = pad_sep_y + pad[1] + 2 * slk_offset if pins == 3: overpads_x_slk = pad_sep_x * 2 + pad[0] + 2 * slk_offset overpads_y_slk = pad_sep_y * 2 + pad[1] + 2 * slk_offset elif pins == 6: overpads_x_slk = pad_sep_x * 2 + pad[0] + 2 * slk_offset dip_size = 1 mark_size = max(1.5*pack_bevel,1) upright_mark = False while pack_height < 2 * mark_size or pack_width < 2 * mark_size: mark_size = mark_size / 2 if pack_bevel > 0 and math.fabs(mark_size / pack_bevel) > 0.7 and math.fabs(mark_size / pack_bevel) < 1.3: upright_mark = True h_fab = pack_height w_fab = pack_width l_fab = -w_fab / 2 t_fab = -h_fab / 2 r_fab = pack_width / 10 h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset dip_size_slk = dip_size mark_l_slk = -overpads_x_slk / 2 if math.fabs(l_slk - mark_l_slk) < 2 * lw_slk: mark_l_slk = l_slk - 2 * lw_slk mark_b_slk = overpads_y_slk / 2 if math.fabs(t_slk + h_slk - mark_b_slk) < 2 * lw_slk: mark_b_slk = t_slk + h_slk + 2 * lw_slk w_crt = max(overpad_width, pack_width) + 2 * crt_offset h_crt = max(overpad_height, pack_height) + 2 * crt_offset l_crt = -w_crt / 2 t_crt = -h_crt / 2 print(fpname) desc = description + ", {0:2.1f}x{1:2.1f}mm^2 package".format(pack_width, pack_height) tag_s = tags + " {0:2.1f}x{1:2.1f}mm^2 package".format(pack_width, pack_height) # init kicad footprint kicad_mod = Footprint(fpname) kicad_mod.setDescription(desc) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 kicad_mod.setAttribute('smd') offset = [0, 0] kicad_modg = kicad_mod # set general values kicad_modg.append( Text(type='reference', text='REF**', at=[0, min(t_slk, -overpad_height / 2, -pack_height / 2) - txt_offset], layer='F.SilkS')) # kicad_modg.append(Text(type='user', text='%R', at=[0, min(t_slk,-overpad_height/2,-pack_height/2)-txt_offset], layer='F.Fab')) kicad_modg.append( Text(type='value', text=fpname, at=[0, max(t_slk + h_slk, overpad_height / 2, pack_height / 2) + txt_offset], layer='F.Fab')) # create FAB-layer if style == 'hc49': THTQuartzRect(kicad_modg, [l_fab, t_fab], [w_fab, h_fab], [w_fab * 0.9, h_fab * 0.9], 'F.Fab', lw_fab) elif style == 'dip': DIPRectL(kicad_modg, [l_fab, t_fab], [w_fab, h_fab], 'F.Fab', lw_fab, dip_size) elif style == 'rect1bevel': bevelRectBL(kicad_modg, [l_fab, t_fab], [w_fab, h_fab], 'F.Fab', lw_fab, dip_size) else: allBevelRect(kicad_modg, [l_fab, t_fab], [w_fab, h_fab], 'F.Fab', lw_fab, pack_bevel) if upright_mark: kicad_modg.append(Line(start=[l_fab + max(mark_size, pack_bevel), t_fab], end=[l_fab + max(mark_size, pack_bevel), t_fab + h_fab], layer='F.Fab', width=lw_fab)) else: kicad_modg.append( Line(start=[l_fab, t_fab + h_fab - mark_size], end=[l_fab + mark_size, t_fab + h_fab], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer if pins == 2: if pack_height < pad[1]: kicad_modg.append( Line(start=[-betweenpads_x_slk / 2, t_slk], end=[betweenpads_x_slk / 2, t_slk], layer='F.SilkS', width=lw_slk)) kicad_modg.append( Line(start=[-betweenpads_x_slk / 2, t_slk + h_slk], end=[betweenpads_x_slk / 2, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) # pin1 mark kicad_modg.append(Line(start=[min(l_slk, -overpads_x_slk / 2), -pad[1] / 2], end=[min(l_slk, -overpads_x_slk / 2), pad[1] / 2], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(PolygoneLine(polygone=[[l_slk + w_slk, t_slk], [-overpads_x_slk / 2, t_slk], [-overpads_x_slk / 2, t_slk + h_slk], [l_slk + w_slk, t_slk + h_slk], ], layer='F.SilkS', width=lw_slk)) elif pins == 3: if (pack_height < overpad_height and pack_width > overpad_width): kicad_modg.append(PolygoneLine(polygone=[[overpads_x_slk / 2, t_slk], [l_slk + w_slk, t_slk], [l_slk + w_slk, t_slk + h_slk], [overpads_x_slk / 2, t_slk + h_slk]], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk - 2 * lw_slk, t_slk], end=[l_slk - 2 * lw_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) kicad_modg.append(PolygoneLine(polygone=[[-overpads_x_slk / 2, mark_b_slk], [-overpads_x_slk / 2, t_slk + h_slk], [l_slk, t_slk + h_slk], [l_slk, t_slk], [-overpads_x_slk / 2, t_slk]], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(PolygoneLine(polygone=[[-overpads_x_slk / 2, -overpads_y_slk / 2], [-overpads_x_slk / 2, overpads_y_slk / 2], [overpads_x_slk / 2, overpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) elif pins >= 4: if (betweenpads_y_slk < 5 * lw_slk or betweenpads_x_slk < 5 * lw_slk) and (pack_height < overpad_height and pack_width < overpad_width): kicad_modg.append(PolygoneLine(polygone=[[-overpads_x_slk / 2, -overpads_y_slk / 2], [-overpads_x_slk / 2, overpads_y_slk / 2], [overpads_x_slk / 2, overpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) else: if (pack_height < overpad_height and pack_width < overpad_width): kicad_modg.append(PolygoneLine(polygone=[[mark_l_slk, betweenpads_y_slk / 2], [l_slk, betweenpads_y_slk / 2], [l_slk, -betweenpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) kicad_modg.append(PolygoneLine(polygone=[[l_slk + w_slk, -betweenpads_y_slk / 2], [l_slk + w_slk, betweenpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) if pins == 4: kicad_modg.append(PolygoneLine(polygone=[[-betweenpads_x_slk / 2, t_slk], [betweenpads_x_slk / 2, t_slk]], layer='F.SilkS', width=lw_slk)) kicad_modg.append(PolygoneLine(polygone=[[betweenpads_x_slk / 2, t_slk + h_slk], [-betweenpads_x_slk / 2, t_slk + h_slk], [-betweenpads_x_slk / 2, mark_b_slk]], layer='F.SilkS', width=lw_slk)) elif (pack_height < overpad_height and pack_width > overpad_width): kicad_modg.append(PolygoneLine(polygone=[[overpads_x_slk / 2, t_slk], [l_slk + w_slk, t_slk], [l_slk + w_slk, t_slk + h_slk], [overpads_x_slk / 2, t_slk + h_slk]], layer='F.SilkS', width=lw_slk)) if pins == 4: kicad_modg.append(PolygoneLine(polygone=[[-betweenpads_x_slk / 2, t_slk], [betweenpads_x_slk / 2, t_slk]], layer='F.SilkS', width=lw_slk)) if style == 'dip': DIPRectL_LeftOnly(kicad_modg, [l_slk, t_slk], [(w_slk - overpads_x_slk) / 2, h_slk], 'F.SilkS', lw_slk, dip_size_slk) kicad_modg.append( Line(start=[betweenpads_x_slk / 2, t_slk + h_slk], end=[-betweenpads_x_slk / 2, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(PolygoneLine(polygone=[[-overpads_x_slk / 2, mark_b_slk], [-overpads_x_slk / 2, t_slk + h_slk], [l_slk, t_slk + h_slk], [l_slk, t_slk], [-overpads_x_slk / 2, t_slk]], layer='F.SilkS', width=lw_slk)) if pins==4: kicad_modg.append(PolygoneLine(polygone=[[betweenpads_x_slk / 2, t_slk + h_slk], [-betweenpads_x_slk / 2, t_slk + h_slk], [-betweenpads_x_slk / 2, mark_b_slk]], layer='F.SilkS', width=lw_slk)) elif (pack_height > overpad_height and pack_width < overpad_width): kicad_modg.append(PolygoneLine(polygone=[[l_slk, -overpads_y_slk / 2], [l_slk, t_slk], [l_slk + w_slk, t_slk], [l_slk + w_slk, -overpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) kicad_modg.append(PolygoneLine(polygone=[[mark_l_slk, overpads_y_slk / 2], [l_slk, overpads_y_slk / 2], [l_slk, t_slk + h_slk], [l_slk + w_slk, t_slk + h_slk], [l_slk + w_slk, overpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) if pins == 4: kicad_modg.append(PolygoneLine(polygone=[[mark_l_slk, betweenpads_y_slk / 2], [l_slk, betweenpads_y_slk / 2], [l_slk, -betweenpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) kicad_modg.append(PolygoneLine(polygone=[[l_slk + w_slk, -betweenpads_y_slk / 2], [l_slk + w_slk, betweenpads_y_slk / 2]], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads pad_type = Pad.TYPE_SMT pad_shape1 = Pad.SHAPE_RECT pad_layers = 'F' ddrill = 0 if (pins == 2): kicad_modg.append(Pad(number=1, type=pad_type, shape=pad_shape1, at=[-pad_sep_x / 2, 0], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append(Pad(number=2, type=pad_type, shape=pad_shape1, at=[pad_sep_x / 2, 0], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) elif (pins == 3): kicad_modg.append(Pad(number=1, type=pad_type, shape=pad_shape1, at=[-pad_sep_x, 0], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append(Pad(number=2, type=pad_type, shape=pad_shape1, at=[0, 0], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append(Pad(number=3, type=pad_type, shape=pad_shape1, at=[pad_sep_x, 0], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) elif (pins == 4): kicad_modg.append( Pad(number=1, type=pad_type, shape=pad_shape1, at=[-pad_sep_x / 2, pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=2, type=pad_type, shape=pad_shape1, at=[pad_sep_x / 2, pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=3, type=pad_type, shape=pad_shape1, at=[pad_sep_x / 2, -pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=4, type=pad_type, shape=pad_shape1, at=[-pad_sep_x / 2, -pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) elif (pins == 6): kicad_modg.append( Pad(number=1, type=pad_type, shape=pad_shape1, at=[-pad_sep_x , pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=2, type=pad_type, shape=pad_shape1, at=[0, pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=3, type=pad_type, shape=pad_shape1, at=[pad_sep_x , pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=4, type=pad_type, shape=pad_shape1, at=[pad_sep_x , -pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=5, type=pad_type, shape=pad_shape1, at=[0, -pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append( Pad(number=6, type=pad_type, shape=pad_shape1, at=[-pad_sep_x, -pad_sep_y / 2], size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) if hasAdhesive: fillCircle(kicad_modg, center=adhesivePos, radius=adhesiveSize / 2, width=0.1, layer='F.Adhes') # add model kicad_modg.append( Model(filename=lib_name + ".3dshapes/" + fpname + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(fpname + '.kicad_mod') def makeCrystalAll(footprint_name, rm, pad_size, ddrill, pack_width, pack_height, pack_offset, pack_rm, style="flat", package_pad=False, package_pad_add_holes=False, package_pad_offset=0, package_pad_size=[0, 0], package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, description="Crystal THT", lib_name="Crystals", tags="", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], name_addition="", pad_style="tht", script3d="", height3d=4.65, iheight3d=4): makeCrystal(footprint_name, rm, pad_size, ddrill, pack_width, pack_height, pack_offset, pack_rm, style, False, False, package_pad_offset, package_pad_size, package_pad_drill_size, package_pad_ddrill, description, lib_name, tags, offset3d, scale3d, rotate3d, name_addition, pad_style, script3d, height3d, iheight3d) if package_pad: makeCrystal(footprint_name, rm, pad_size, ddrill, pack_width, pack_height, pack_offset, pack_rm, style, True, False, package_pad_offset, package_pad_size, package_pad_drill_size, package_pad_ddrill, description, lib_name, tags, offset3d, scale3d, rotate3d, name_addition + "_1EP_style1", pad_style, script3d, height3d, iheight3d) if package_pad_add_holes and package_pad: makeCrystal(footprint_name, rm, pad_size, ddrill, pack_width, pack_height, pack_offset, pack_rm, style, True, True, package_pad_offset, package_pad_size, package_pad_drill_size, package_pad_ddrill, description, lib_name, tags, offset3d, scale3d, rotate3d, name_addition + "_1EP_style2", pad_style, script3d, height3d, iheight3d) # +---------------------------------------------------------------+ ^ # OOOOO | | | # OO1OO----^--- | | | # OOOOO | ----+ ^ | | # | | | | | # rm | pack_rm | pack_height # | | | | | # OOOOO | ----+ v | | # OO2OO ---v--- | | | # OOOOO | | | # +---------------------------------------------------------------+ v # <-----------------pack_width------------------------------------> # <------------->pack_offset # # # pins=2,3 # style="flat"/"hc49" # pad_style=tht/smd for pin 1/2 def makeCrystal(footprint_name, rm, pad_size, ddrill, pack_width, pack_height, pack_offset, pack_rm, style="flat", package_pad=False, package_pad_add_holes=False, package_pad_offset=0, package_pad_size=[0, 0], package_pad_drill_size=[1.2, 1.2], package_pad_ddrill=0.8, description="Crystal THT", lib_name="Crystals", tags="", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], name_addition="", pad_style="tht", script3d="", height3d=4.65, iheight3d=4): fpname = footprint_name fpname = fpname + name_addition if type(pad_size) is list: pad=[pad_size[1],pad_size[0]] else: pad = [pad_size, pad_size] pad3pos = [rm / 2, package_pad_offset + package_pad_size[0] / 2] pad3dril_xoffset = package_pad_size[1] / 2 + package_pad_ddrill / 2 h_fab = pack_width w_fab = pack_height l_fab = -(w_fab - rm) / 2 t_fab = pack_offset h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset bev = 0 if style == "hc49": bev = min(0.35, max(2 * lw_slk, w_slk / 7)) slk_u_line=False if package_pad: if (package_pad_size[1] < pack_width / 2): h_slk=math.fabs((pad3pos[1]-package_pad_size[0]/2-slk_offset)-t_slk) slk_u_line = True else: h_slk = max(t_slk + h_slk, pad3pos[1] + package_pad_size[0] / 2 + slk_offset) - t_slk l_slk = min(l_slk, rm / 2 - package_pad_size[1] / 2 - slk_offset) w_slk = max(l_slk+w_slk, rm / 2 + package_pad_size[1] / 2 + slk_offset)-l_slk if package_pad_add_holes: l_crt = pad3pos[0] - pad3dril_xoffset - package_pad_drill_size[0] / 2 - crt_offset extra_textoffset = 0 if (l_slk>-(pad[0]/2+slk_offset+lw_slk)): extra_textoffset=pad[0]/2+slk_offset+lw_slk-0.5 t_crt = -pad[1] / 2 - crt_offset w_crt = max(pack_height + 2 * bev + 4 * crt_offset, pad[0] + rm, w_slk) + 2 * crt_offset h_crt = max(t_slk + h_slk - t_crt, pad3pos[1] + package_pad_size[0] / 2-t_crt-crt_offset,pack_width + pack_offset+pad[1]/2) + 2 * crt_offset l_crt = rm / 2 - w_crt / 2 if package_pad and package_pad_add_holes and (pad[1] # <-------------rm------------------> # # # pins=2,3 def makeCrystalHC49Vert(footprint_name, pins, rm, pad_size, ddrill, pack_width, pack_height, innerpack_width, innerpack_height, description="Crystal THT", lib_name="Crystals", tags="", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], addSizeFootprintName=False, script3d="", height3d=10): fpname = footprint_name desc = description tag_s = tags if addSizeFootprintName: fpname += "-{2}pin_w{0:2.1f}mm_h{1:2.1f}mm".format(pack_width, pack_height, pins) desc = description + ", length*width={0:2.1f}x{1:2.1f}mm^2 package, package length={0:2.1f}mm, package width={1:2.1f}mm, {2} pins".format(pack_width, pack_height,pins) tag_s = tags + " {0:2.1f}x{1:2.1f}mm^2 package length {0:2.1f}mm width {1:2.1f}mm {2} pins".format(pack_width, pack_height,pins) if type(pad_size) is list: pad = [pad_size[1], pad_size[0]] else: pad = [pad_size, pad_size] centerpos=[rm/2,0] pin1pos=[0,0] pin2pos=[rm,0] pin3pos = [rm / 2, 0] if (pins==3): pin2pos = [rm/2, 0] pin3pos = [rm, 0] w_fab = pack_width h_fab = pack_height l_fab = -(w_fab - rm) / 2 t_fab = -h_fab/2 iw_fab = innerpack_width ih_fab = innerpack_height il_fab = -(iw_fab - rm) / 2 it_fab = -ih_fab/2 incomplete_slk=False h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset l_crt=l_slk-crt_offset t_crt=t_slk-crt_offset w_crt=w_slk+2*crt_offset h_crt = h_slk + 2 * crt_offset if pack_width # <-------------rm--------> # # # pins=2,3 def makeCrystalRoundVert(footprint_name, rm, pad_size, ddrill, pack_diameter, description="Crystal THT", lib_name="Crystals", tags="", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0]): fpname = footprint_name if type(pad_size) is list: pad = [pad_size[1], pad_size[0]] else: pad = [pad_size, pad_size] centerpos = [rm / 2, 0] pin1pos = [0, 0] pin2pos = [rm, 0] d_fab = pack_diameter cl_fab = rm / 2 ct_fab = 0 d_slk = d_fab + 2 * slk_offset cl_slk = cl_fab ct_slk = ct_fab sl_slk = 0 if d_fab >= rm + pad[0]: st_slk = 0 sl_slk = min(-(d_fab - rm) / 2, - pad[0] / 2) - slk_offset alpha_slk = 180 elif d_slk * d_slk / 4 >= rm * rm / 4: st_slk = -max(math.sqrt(d_slk * d_slk / 4 - rm * rm / 4), pad[1] / 2 + slk_offset) alpha_slk = 2 * ( 90 - math.fabs(180 / 3.1415 * math.atan(math.fabs(st_slk - centerpos[1]) / math.fabs(sl_slk - centerpos[0])))) else: st_slk = -pad[1] / 2 - slk_offset alpha_slk = 2 * ( 90 - math.fabs(180 / 3.1415 * math.atan(math.fabs(st_slk - centerpos[1]) / math.fabs(sl_slk - centerpos[0])))) d_crt = max(rm + pad[0], d_slk) + 2 * crt_offset cl_crt = cl_fab ct_crt = ct_fab print(fpname) desc = description tag_s = tags # init kicad footprint kicad_mod = Footprint(fpname) kicad_mod.setDescription(desc) kicad_mod.setTags(tags) offset = [0, 0] kicad_modg = kicad_mod # set general values kicad_modg.append( Text(type='reference', text='REF**', at=[centerpos[0], ct_slk - d_slk / 2 - txt_offset], layer='F.SilkS')) kicad_modg.append( Text(type='value', text=fpname, at=[centerpos[0], ct_slk + d_slk / 2 + txt_offset], layer='F.Fab')) # create FAB-layer kicad_mod.append(Circle(center=[cl_fab, ct_fab], radius=d_fab / 2, layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer kicad_mod.append( Arc(center=[cl_slk, ct_slk], start=[sl_slk, st_slk], angle=alpha_slk, layer='F.SilkS', width=lw_slk)) kicad_mod.append( Arc(center=[cl_slk, ct_slk], start=[sl_slk, -st_slk], angle=-alpha_slk, layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(Circle(center=[cl_crt, ct_crt], radius=d_crt / 2, layer='F.CrtYd', width=lw_crt)) # create pads pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_CIRCLE pad_layers = '*' kicad_modg.append(Pad(number=1, type=pad_type, shape=pad_shape1, at=pin1pos, size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) kicad_modg.append(Pad(number=2, type=pad_type, shape=pad_shape1, at=pin2pos, size=pad, drill=ddrill, layers=[pad_layers + '.Cu', pad_layers + '.Mask'])) # add model kicad_modg.append( Model(filename=lib_name + ".3dshapes/" + fpname + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(fpname + '.kicad_mod') ================================================ FILE: scripts/tools/footprint_scripts_dsub.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * # NOQA from math import sqrt crt_offset = 0.5 # different for connectors def makeDSubStraight(pins, isMale, HighDensity, rmx, rmy, pindrill, pad, mountingdrill, mountingpad, mountingdistance, outline_size, outline_cornerradius, connwidth, connheight, side_angle_degree, conn_cornerradius, tags_additional=[], lib_name="${{KISYS3DMOD}}/Connectors_DSub", classname="DSub", classname_description="D-Sub connector", webpage="", HighDensityOffsetMidLeft=0): hasMountingHoles=mountingdrill>0 and mountingdistance>0 # rectangular outside of connector outer part on F.Fab w_fab = outline_size[0] h_fab = outline_size[1] l_fab = -w_fab/2 t_fab = -h_fab/2 # rectangular outside of connector inner part on F.Fab wi_fab = connwidth hi_fab = connheight li_fab = -wi_fab/2 ti_fab = -hi_fab/2 # rectangular outside of connector outer part on silkscreen h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset # rectangular outside of connector inner part on silkscreen hi_slk = hi_fab + 2 * slk_offset wi_slk = wi_fab + 2 * slk_offset li_slk = li_fab - slk_offset ti_slk = ti_fab - slk_offset package_size=[0,0]; w_crt = max([w_fab, mountingpad+mountingdistance, mountingpad+mountingdistance])+2*crt_offset h_crt = max([h_fab, mountingpad, mountingdrill])+2*crt_offset l_crt = -w_crt/2 t_crt = -h_crt/2 text_size = w_fab*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 description = "{0}-pin {1}, straight/vertical, THT-mount".format(pins, classname_description) tags = "{0}-pin {1} straight vertical THT".format(pins, classname_description) footprint_name="{0}-{1}".format(classname,pins) if HighDensity: footprint_name=footprint_name+"-HD" if isMale: description = description+", male" tags = tags+" male" footprint_name=footprint_name+"_Male" else: description = description+", female" tags = tags+" female" footprint_name=footprint_name+"_Female" description = description+", pitch {0}x{1}mm".format(rmx,rmy) tags = tags+" pitch {0}x{1}mm".format(rmx,rmy) footprint_name=footprint_name+"_Vertical" footprint_name=footprint_name+"_Pitch{0:3.2f}x{1:3.2f}mm".format(rmx,rmy) description = description+", distance of mounting holes {0}mm".format(mountingdistance) tags = tags+" mounting holes distance {0}mm".format(mountingdistance) #footprint_name=footprint_name+"_MHDist{0:3.2f}mm".format(mountingdistance) if hasMountingHoles: footprint_name=footprint_name+"_MountingHoles" if len(webpage)>0: description = description+", see {0}".format(webpage) if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) pinstop=int((pins + 1)/2) pinsmid=0 pinsbot=int((pins - 1)/2) drmy=rmy/2 if HighDensity: pinstop=int((pins+1)/3) pinsmid=pinstop pinsbot=pins-pinstop-pinsbot drmy=rmy y1=-drmy x10=-(pinstop-1)/2*rmx topoffset=0 botoffset=rmx/2 if HighDensity: x10=-mountingdistance/2+HighDensityOffsetMidLeft topoffset=rmx/2 botoffset=rmx/2 # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 if not isMale: offset=[x10+topoffset,drmy] else: offset=[-(topoffset+x10),drmy] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.SilkS')) kicad_modg.append(Text(type='user', text='%R', at=[0,0], layer='F.Fab', size=text_size ,thickness=text_t)) kicad_modg.append(Text(type='value', text=footprint_name, at=[l_fab+w_fab/2, t_slk + h_slk + txt_offset], layer='F.Fab')) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT hole_type = Pad.TYPE_NPTH pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_CIRCLE pad_layers = Pad.LAYERS_THT keepouts=[]; y1=-drmy x1pos=0 if isMale: x1=x10+topoffset else: x1=-x10-topoffset for p in range(1, pinstop+1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad+8*slk_offset, pad+8*slk_offset) x1pos=x1 else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x1, y1, pad+(slk_pad_offset+2*lw_slk), pad+(slk_pad_offset+2*lw_slk)) if isMale: x1=x1+rmx else: x1=x1-rmx if HighDensity: if isMale: x1=x10; else: x1=-x10; y1=0 for p in range(pinstop+1, pinstop+pinsmid+1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad+8*slk_offset, pad+8*slk_offset) else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x1, y1, pad+(slk_pad_offset+2*lw_slk), pad+(slk_pad_offset+2*lw_slk)) if isMale: x1=x1+rmx else: x1=x1-rmx if isMale: x1=x10+botoffset else: x1=-x10-botoffset y1=drmy for p in range(pinstop+pinsmid+1, pins+1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad+8*slk_offset, pad+8*slk_offset) else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x1, y1, pad+(slk_pad_offset+2*lw_slk), pad+(slk_pad_offset+2*lw_slk)) if isMale: x1=x1+rmx else: x1=x1-rmx if hasMountingHoles and mountingpad>0: kicad_modg.append(Pad(number=0, type=pad_type, shape=pad_shapeother, at=[-mountingdistance/2, 0], size=[mountingpad,mountingpad], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(-mountingdistance/2, 0, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) kicad_modg.append(Pad(number=0, type=pad_type, shape=pad_shapeother, at=[mountingdistance/2, 0], size=[mountingpad,mountingpad], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(mountingdistance/2, 0, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) if hasMountingHoles and mountingpad<=0: kicad_modg.append(Pad(number=0, type=hole_type, shape=pad_shapeother, at=[-mountingdistance/2, 0], size=[0,0], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(-mountingdistance/2, 0, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) kicad_modg.append(Pad(number=0, type=hole_type, shape=pad_shapeother, at=[mountingdistance/2, 0], size=[0,0], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(mountingdistance/2, 0, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) # outline addRoundedRect(kicad_modg, [l_fab, t_fab], [w_fab, h_fab], outline_cornerradius, layer='F.Fab', width=lw_fab) addRoundedRect(kicad_modg, [l_slk, t_slk], [w_slk, h_slk], outline_cornerradius+slk_offset, layer='F.SilkS', width=lw_slk) #pin1 mark allEqualSidedDownTriangle(kicad_modg, xcenter=[x1pos, -h_slk/2-text_size[0]*0.75], side_length=text_size[0]/2, layer='F.SilkS', width=lw_slk) # connector_inside allRoundedBevelRect(kicad_modg, [li_fab, ti_fab], [wi_fab, hi_fab], side_angle_degree, conn_cornerradius, layer='F.Fab', width=lw_fab) allRoundedBevelRect(kicad_modg, [li_slk, ti_slk], [wi_slk, hi_slk], side_angle_degree, conn_cornerradius+slk_offset, layer='F.SilkS', width=lw_slk) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # add model kicad_mod.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0,0,0], scale=[1,1,1], rotate=[0,0,0])) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') def makeDSubEdge(pins, isMale, rmx, pad, mountingdrill, mountingdistance, shield_width, connwidth, can_height, shieldthickness, backcan_width, backcan_height, smaller_backcan_offset, smaller_backcan_height, soldercup_length, soldercup_diameter,soldercup_pad_edge_offset, tags_additional=[], lib_name="${{KISYS3DMOD}}/Connectors_DSub", classname="DSub", classname_description="D-Sub connector", webpage=""): w_slk=int((pins-1)/2)*rmx+pad[0]+(slk_pad_offset+2*lw_slk) h_slk=pad[1] l_slk=-w_slk/2 t_slk=-h_slk/2 text_size = w_slk*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 description = "{0}-pin {1}, solder-cups edge-mounted".format(pins, classname_description) tags = "{0}-pin {1} edge mount solder cup".format(pins, classname_description) footprint_name="{0}-{1}".format(classname,pins) if isMale: description = description+", male" tags = tags+" male" footprint_name=footprint_name+"_Male" else: description = description+", female" tags = tags+" female" footprint_name=footprint_name+"_Female" description = description+", x-pin-pitch {0}mm".format(rmx) tags = tags+" x-pin-pitch {0}mm".format(rmx) footprint_name=footprint_name+"_EdgeMount" footprint_name=footprint_name+"_Pitch{0:3.2f}mm".format(rmx) description = description+", distance of mounting holes {0}mm".format(mountingdistance) tags = tags+" mounting holes distance {0}mm".format(mountingdistance) #footprint_name=footprint_name+"_MHDist{0:3.2f}mm".format(mountingdistance) if len(webpage)>0: description = description+", see {0}".format(webpage) if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) pinstop=int((pins + 1)/2) pinsbot=int((pins - 1)/2) y1=-pad[1]/2 x10=-(pinstop-1)/2*rmx topoffset=0 botoffset=rmx/2 # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_mod.setAttribute('smd') # anchor for SMD-symbols is in the center, for THT-sybols at pin1 ypcb_edge=pad[1]/2+soldercup_pad_edge_offset; # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[x10-topoffset-pad[0]/2-text_size[0]*3, 0], layer='F.SilkS')) kicad_mod.append(Text(type='user', text='%R', at=[0,ypcb_edge+smaller_backcan_height/2], layer='F.Fab', size=text_size ,thickness=text_t)) kicad_mod.append(Text(type='value', text=footprint_name, at=[0, ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+can_height+text_size[0]], layer='F.Fab')) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_SMT pad_shape1 = Pad.SHAPE_RECT pad_layers_top = ['F.Cu', 'F.Mask', 'F.Paste'] pad_layers_bot = ['B.Cu', 'B.Mask', 'B.Paste'] slk_layers_top = 'F.SilkS' slk_layers_bot = 'B.SilkS' keepouts=[]; y1=0 if isMale: x1=x10+topoffset else: x1=-x10-topoffset x_pin1=0; leftmost=0 rightmost=0 for p in range(1, pinstop+1): kicad_mod.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=0, layers=pad_layers_top)) keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) kicad_mod.append(RectLine(start=[x1-soldercup_diameter/2, ypcb_edge-soldercup_length], end=[x1+soldercup_diameter/2, ypcb_edge], layer='F.Fab', width=lw_fab)) if p==1: x_pin1=x1; leftmost=min(leftmost, x1-pad[0]/2) rightmost=max(rightmost, x1+pad[0]/2) if isMale: x1=x1+rmx else: x1=x1-rmx if isMale: x1=x10+botoffset else: x1=-x10-botoffset y1=0 for p in range(pinstop+1, pins+1): kicad_mod.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=0, layers=pad_layers_bot)) keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) kicad_mod.append(RectLine(start=[x1-soldercup_diameter/2, ypcb_edge-soldercup_length], end=[x1+soldercup_diameter/2, ypcb_edge], layer='B.Fab', width=lw_fab)) leftmost=min(leftmost, x1-pad[0]/2) rightmost=max(rightmost, x1+pad[0]/2) if isMale: x1=x1+rmx else: x1=x1-rmx smaller_backcup_width=backcan_width-2*smaller_backcan_offset #fabrication_layer kicad_mod.append(RectLine(start=[-smaller_backcup_width/2, ypcb_edge], end=[smaller_backcup_width/2, ypcb_edge+smaller_backcan_height], layer='F.Fab', width=lw_fab)) kicad_mod.append(RectLine(start=[-backcan_width/2, ypcb_edge+smaller_backcan_height], end=[backcan_width/2, ypcb_edge+smaller_backcan_height+backcan_height], layer='F.Fab', width=lw_fab)) kicad_mod.append(RectLine(start=[-shield_width/2, ypcb_edge+smaller_backcan_height+backcan_height], end=[shield_width/2, ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness], layer='F.Fab', width=lw_fab)) kicad_mod.append(RectLine(start=[-connwidth/2, ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness], end=[connwidth/2, ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+can_height], layer='F.Fab', width=lw_fab)) # create courtyard kicad_mod.append(PolygoneLine(polygone=[[roundCrt(leftmost-crt_offset), roundCrt(-pad[1]/2-crt_offset)], [roundCrt(rightmost + crt_offset), roundCrt(-pad[1]/2-crt_offset)], [roundCrt(rightmost + crt_offset), roundCrt(ypcb_edge-crt_offset)], [roundCrt(smaller_backcup_width/2 + crt_offset), roundCrt(ypcb_edge-crt_offset)], [roundCrt(smaller_backcup_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height-crt_offset)], [roundCrt(backcan_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height-crt_offset)], [roundCrt(backcan_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height-crt_offset)], [roundCrt(shield_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height-crt_offset)], [roundCrt(shield_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+crt_offset)], [roundCrt(connwidth/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+crt_offset)], [roundCrt(connwidth/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+can_height+crt_offset)], [-roundCrt(connwidth/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+can_height+crt_offset)], [-roundCrt(connwidth/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+crt_offset)], [-roundCrt(shield_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height+shieldthickness+crt_offset)], [-roundCrt(shield_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height-crt_offset)], [-roundCrt(backcan_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height+backcan_height-crt_offset)], [-roundCrt(backcan_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height-crt_offset)], [-roundCrt(smaller_backcup_width/2 + crt_offset), roundCrt(ypcb_edge+smaller_backcan_height-crt_offset)], [-roundCrt(smaller_backcup_width/2 + crt_offset), roundCrt(ypcb_edge-crt_offset)], [-roundCrt(rightmost + crt_offset), roundCrt(ypcb_edge-crt_offset)], [-roundCrt(rightmost + crt_offset), roundCrt(-pad[1]/2-crt_offset)] ], layer='F.CrtYd', width=lw_crt)) #silkscreen + PDB-edge kicad_mod.append(PolygoneLine(polygone=[[-x10+topoffset+pad[0]/2+slk_pad_offset, y1+pad[1]/2], [-x10+topoffset+pad[0]/2+slk_pad_offset, y1-pad[1]/2-slk_pad_offset], [x10-topoffset-pad[0]/2-slk_pad_offset, y1-pad[1]/2-slk_pad_offset], [x10-topoffset-pad[0]/2-slk_pad_offset, y1+pad[1]/2]], layer=slk_layers_top, width=lw_slk)) if isMale: kicad_mod.append(PolygoneLine(polygone=[[x_pin1-topoffset-pad[0]/2-(slk_pad_offset+2*lw_slk), y1], [x_pin1-topoffset-pad[0]/2-(slk_pad_offset+2*lw_slk), y1-pad[1]/2-(slk_pad_offset+2*lw_slk)], [x_pin1-topoffset+rmx, y1-pad[1]/2-(slk_pad_offset+2*lw_slk)]], layer=slk_layers_top, width=lw_slk)) else: kicad_mod.append(PolygoneLine(polygone=[[x_pin1+topoffset+pad[0]/2+(slk_pad_offset+2*lw_slk), y1], [x_pin1+topoffset+pad[0]/2+(slk_pad_offset+2*lw_slk), y1-pad[1]/2-(slk_pad_offset+2*lw_slk)], [x_pin1+topoffset-rmx, y1-pad[1]/2-(slk_pad_offset+2*lw_slk)]], layer=slk_layers_top, width=lw_slk)) kicad_mod.append(Line(start=[-shield_width/2, ypcb_edge], end=[shield_width/2, pad[1]/2+soldercup_pad_edge_offset], layer='Dwgs.User', width=lw_crt)) kicad_mod.append(Text(type='user', text='PCB edge', at=[-shield_width/2+5*text_size[0], ypcb_edge-text_size[1]*2/3], layer='Dwgs.User', size=[text_size[0]/2,text_size[1]/2] ,thickness=text_t/2)) # add model kicad_mod.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0,0,0], scale=[1,1,1], rotate=[0,0,0])) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') def makeDSubAngled(pins, isMale, HighDensity, rmx, rmy, pindrill, pad, pin_pcb_distance, mountingdrill, mountingpad, mountingdistance, mounting_pcb_distance, shield_width, shield_thickness, can_width, can_height, backbox_width, backbox_height, nut_diameter, nut_length, backcan_width=0, backcan_height=0, tags_additional=[], lib_name="${{KISYS3DMOD}}/Connectors_DSub", classname="DSub", classname_description="D-Sub connector", webpage="", HighDensityOffsetMidLeft=0): hasMountingHoles=mountingdrill>0 and mountingdistance>0 hasNoBackBox=backcan_width*backcan_height>0 and backbox_width*backbox_height==0 text_size = 1 text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 description = "{0}-pin {1}, horizontal/angled (90 deg), THT-mount".format(pins, classname_description) tags = "{0}-pin {1} horizontal angled 90deg THT".format(pins, classname_description) footprint_name="{0}-{1}".format(classname,pins) if HighDensity: footprint_name=footprint_name+"-HD" if isMale: description = description+", male" tags = tags+" male" footprint_name=footprint_name+"_Male" else: description = description+", female" tags = tags+" female" footprint_name=footprint_name+"_Female" rmy_default=2.84 description = description+", pitch {0}x{1}mm, pin-PCB-offset {2}mm".format(rmx,rmy,pin_pcb_distance) tags = tags+" pitch {0}x{1}mm pin-PCB-offset {2}mm".format(rmx,rmy,pin_pcb_distance) footprint_name=footprint_name+"_Horizontal" footprint_name=footprint_name+"_Pitch{0:3.2f}x{1:3.2f}mm".format(rmx,rmy) footprint_name=footprint_name+"_EdgePinOffset{0:3.2f}mm".format(pin_pcb_distance) if hasMountingHoles: description = description+", distance of mounting holes {0}mm, distance of mounting holes to PCB edge {1}mm".format(mountingdistance, mounting_pcb_distance) tags = tags+" mounting-holes-distance {0}mm mounting-hole-offset {0}mm".format(mountingdistance, mounting_pcb_distance) if not hasNoBackBox: footprint_name=footprint_name+"_Housed" footprint_name=footprint_name+"_MountingHolesOffset{0:3.2f}mm".format(mounting_pcb_distance) else: if not hasNoBackBox: footprint_name=footprint_name+"_Housed" if len(webpage)>0: description = description+", see {0}".format(webpage) if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) rows=2 pinstop=int((pins + 1)/2) pinsmid=0 pinsbot=int((pins - 1)/2) drmy=rmy/2 if HighDensity: rows=3 pinstop=int((pins+1)/3) pinsmid=pinstop pinsbot=pins-pinstop-pinsbot drmy=rmy y1=-drmy x10=-(pinstop-1)/2*rmx topoffset=0 botoffset=rmx/2 if HighDensity: x10=-mountingdistance/2+HighDensityOffsetMidLeft topoffset=rmx/2 botoffset=rmx/2 ypcb_edge=drmy+pin_pcb_distance back_height=backbox_height if hasNoBackBox: back_height=pin_pcb_distance+rmy*(rows-1)+pad/2 w_crt = max([backbox_width, shield_width])+2*crt_offset h_crt = max([backbox_height, mounting_pcb_distance+mountingpad/2])+max([nut_length, can_height])+shield_thickness+2*crt_offset if hasNoBackBox: h_crt = back_height+max([nut_length, can_height])+shield_thickness+2*crt_offset l_crt = -w_crt/2 t_crt = -max([backbox_height-pin_pcb_distance-drmy, drmy+pad/2])-crt_offset # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 if not isMale: offset=[x10+topoffset,drmy] else: offset=[-(topoffset+x10),drmy] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[0, ypcb_edge-back_height-text_size[0]], layer='F.SilkS')) kicad_modg.append(Text(type='user', text='%R', at=[0,ypcb_edge+shield_thickness+can_height/2], layer='F.Fab', size=text_size ,thickness=text_t)) kicad_modg.append(Text(type='value', text=footprint_name, at=[0, ypcb_edge+shield_thickness+can_height+text_size[0]*1.5], layer='F.Fab')) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT hole_type = Pad.TYPE_NPTH pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_CIRCLE pad_layers = Pad.LAYERS_THT keepouts=[]; y1=-drmy if isMale: x1=x10+topoffset else: x1=-x10-topoffset x1pos=0 leftmost=0 rightmost=0 for p in range(1, pinstop+1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad+8*slk_offset, pad+8*slk_offset) x1pos=x1 else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x1, y1, pad+(slk_pad_offset+2*lw_slk), pad+(slk_pad_offset+2*lw_slk)) if hasNoBackBox: kicad_modg.append(Line(start=[x1-lw_fab, y1], end=[x1-lw_fab, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[x1, y1], end=[x1, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[x1+lw_fab, y1], end=[x1+lw_fab, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) leftmost=min(leftmost,x1) rightmost=max(rightmost,x1) if isMale: x1=x1+rmx else: x1=x1-rmx if HighDensity: if isMale: x1=x10; else: x1=-x10; y1=0 for p in range(pinstop+1, pinstop+pinsmid+1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad+8*slk_offset, pad+8*slk_offset) else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x1, y1, pad+(slk_pad_offset+2*lw_slk), pad+(slk_pad_offset+2*lw_slk)) if hasNoBackBox: kicad_modg.append(Line(start=[x1-lw_fab, y1], end=[x1-lw_fab, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[x1, y1], end=[x1, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[x1+lw_fab, y1], end=[x1+lw_fab, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) leftmost=min(leftmost,x1) rightmost=max(rightmost,x1) if isMale: x1=x1+rmx else: x1=x1-rmx if isMale: x1=x10+botoffset else: x1=-x10-botoffset y1=drmy for p in range(pinstop+pinsmid+1, pins+1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad+8*slk_offset, pad+8*slk_offset) else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=pindrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(x1, y1, pad+(slk_pad_offset+2*lw_slk), pad+(slk_pad_offset+2*lw_slk)) if hasNoBackBox: kicad_modg.append(Line(start=[x1-lw_fab, y1], end=[x1-lw_fab, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[x1, y1], end=[x1, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[x1+lw_fab, y1], end=[x1+lw_fab, ypcb_edge-backcan_height], layer='F.Fab', width=lw_fab)) leftmost=min(leftmost,x1) rightmost=max(rightmost,x1) if isMale: x1=x1+rmx else: x1=x1-rmx # mounting holes if hasMountingHoles and mountingpad>0: kicad_modg.append(Pad(number=0, type=pad_type, shape=pad_shapeother, at=[-mountingdistance/2, ypcb_edge-mounting_pcb_distance], size=[mountingpad,mountingpad], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(-mountingdistance/2, ypcb_edge-mounting_pcb_distance, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) kicad_modg.append(Pad(number=0, type=pad_type, shape=pad_shapeother, at=[mountingdistance/2, ypcb_edge-mounting_pcb_distance], size=[mountingpad,mountingpad], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(mountingdistance/2, ypcb_edge-mounting_pcb_distance, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) if hasMountingHoles and mountingpad<=0 and backbox_width*backbox_height==0: kicad_modg.append(Pad(number=0, type=hole_type, shape=pad_shapeother, at=[-mountingdistance/2, ypcb_edge-mounting_pcb_distance], size=[0,0], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(-mountingdistance/2, ypcb_edge-mounting_pcb_distance, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) kicad_modg.append(Pad(number=0, type=hole_type, shape=pad_shapeother, at=[mountingdistance/2, ypcb_edge-mounting_pcb_distance], size=[0,0], drill=mountingdrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(mountingdistance/2, ypcb_edge-mounting_pcb_distance, mountingpad+(slk_pad_offset+2*lw_slk), mountingpad+(slk_pad_offset+2*lw_slk)) # PCB edge marker #kicad_modg.append(Line(start=[-shield_width/2, ypcb_edge], end=[shield_width/2, ypcb_edge], layer='Dwgs.User', width=lw_crt)) #kicad_modg.append(Text(type='user', text='PCB edge', at=[-shield_width/2+5*text_size[0], ypcb_edge-text_size[1]*2/3], layer='Dwgs.User', size=[text_size[0]/2,text_size[1]/2] ,thickness=text_t/2)) # outline if not hasNoBackBox: kicad_modg.append(RectLine(start=[-backbox_width/2, ypcb_edge-backbox_height], end=[backbox_width/2, ypcb_edge], layer='F.Fab', width=lw_fab)) else: kicad_modg.append(RectLine(start=[-backcan_width/2, ypcb_edge-backcan_height], end=[backcan_width/2, ypcb_edge], layer='F.Fab', width=lw_fab)) kicad_modg.append(RectLine(start=[-shield_width/2, ypcb_edge], end=[shield_width/2, ypcb_edge+shield_thickness], layer='F.Fab', width=lw_fab)) kicad_modg.append(RectLine(start=[-can_width/2, ypcb_edge+shield_thickness], end=[can_width/2, ypcb_edge+shield_thickness+can_height], layer='F.Fab', width=lw_fab)) if nut_length>0 and nut_diameter>0: kicad_modg.append(RectLine(start=[-mountingdistance/2-nut_diameter/2, ypcb_edge+shield_thickness], end=[-mountingdistance/2+nut_diameter/2, ypcb_edge+shield_thickness+nut_length], layer='F.Fab', width=lw_fab)) kicad_modg.append(RectLine(start=[mountingdistance/2-nut_diameter/2, ypcb_edge+shield_thickness], end=[mountingdistance/2+nut_diameter/2, ypcb_edge+shield_thickness+nut_length], layer='F.Fab', width=lw_fab)) if hasMountingHoles: kicad_modg.append(Line(start=[-mountingdistance/2-mountingdrill/2, ypcb_edge], end=[-mountingdistance/2-mountingdrill/2, ypcb_edge-mounting_pcb_distance], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-mountingdistance/2+mountingdrill/2, ypcb_edge], end=[-mountingdistance/2+mountingdrill/2, ypcb_edge-mounting_pcb_distance], layer='F.Fab', width=lw_fab)) kicad_modg.append(Arc(start=[-mountingdistance/2-mountingdrill/2, ypcb_edge-mounting_pcb_distance], center=[-mountingdistance/2, ypcb_edge-mounting_pcb_distance], angle=180, layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[mountingdistance/2-mountingdrill/2, ypcb_edge], end=[mountingdistance/2-mountingdrill/2, ypcb_edge-mounting_pcb_distance], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[mountingdistance/2+mountingdrill/2, ypcb_edge], end=[mountingdistance/2+mountingdrill/2, ypcb_edge-mounting_pcb_distance], layer='F.Fab', width=lw_fab)) kicad_modg.append(Arc(start=[mountingdistance/2-mountingdrill/2, ypcb_edge-mounting_pcb_distance], center=[mountingdistance/2, ypcb_edge-mounting_pcb_distance], angle=180, layer='F.Fab', width=lw_fab)) # silkscreen if not hasNoBackBox: kicad_modg.append(PolygoneLine(polygone=[ [-backbox_width/2-slk_offset, ypcb_edge-lw_slk/2], [-backbox_width/2-slk_offset, ypcb_edge-backbox_height-slk_offset], [backbox_width/2+slk_offset, ypcb_edge-backbox_height-slk_offset], [backbox_width/2+slk_offset, ypcb_edge-lw_slk/2], ], layer='F.SilkS', width=lw_slk)) allEqualSidedDownTriangle(kicad_modg, xcenter=[x1pos, ypcb_edge-backbox_height-slk_offset-text_size[0]*0.75], side_length=text_size[0]/2, layer='F.SilkS', width=lw_slk) else: kicad_modg.append(PolygoneLine(polygone=[ [-backcan_width/2-slk_offset, ypcb_edge-lw_slk/2], [-backcan_width/2-slk_offset, ypcb_edge-backcan_height-slk_offset], [leftmost-pad/2-slk_pad_offset, ypcb_edge-backcan_height-slk_offset], [leftmost-pad/2-slk_pad_offset, ypcb_edge-back_height-slk_pad_offset], [rightmost+pad/2+slk_pad_offset, ypcb_edge-back_height-slk_pad_offset], [rightmost+pad/2+slk_pad_offset, ypcb_edge-backcan_height-slk_offset], [backcan_width/2+slk_offset, ypcb_edge-backcan_height-slk_offset], [backcan_width/2+slk_offset, ypcb_edge-lw_slk/2], ], layer='F.SilkS', width=lw_slk)) allEqualSidedDownTriangle(kicad_modg, xcenter=[x1pos, ypcb_edge-back_height-slk_offset-text_size[0]*0.75], side_length=text_size[0]/2, layer='F.SilkS', width=lw_slk) # create courtyard if not hasNoBackBox: kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) else: kicad_mod.append(PolygoneLine(polygone=[ [roundCrt(offset[0]-can_width/2-crt_offset), roundCrt(offset[1]+ypcb_edge+shield_thickness+can_height+crt_offset)], [roundCrt(offset[0]-can_width/2-crt_offset), roundCrt(offset[1]+ypcb_edge+shield_thickness+crt_offset)], [roundCrt(offset[0]-shield_width/2-crt_offset), roundCrt(offset[1]+ypcb_edge+shield_thickness+crt_offset)], [roundCrt(offset[0]-shield_width/2-crt_offset), roundCrt(offset[1]+ypcb_edge-crt_offset)], [roundCrt(offset[0]-backcan_width/2-crt_offset), roundCrt(offset[1]+ypcb_edge-crt_offset)], [roundCrt(offset[0]-backcan_width/2-crt_offset), roundCrt(offset[1]+ypcb_edge-backcan_height-crt_offset)], [roundCrt(offset[0]+leftmost-pad/2-crt_offset), roundCrt(offset[1]+ypcb_edge-backcan_height-crt_offset)], [roundCrt(offset[0]+leftmost-pad/2-crt_offset), roundCrt(offset[1]+ypcb_edge-back_height-crt_offset)], [roundCrt(offset[0]+rightmost+pad/2+crt_offset), roundCrt(offset[1]+ypcb_edge-back_height-crt_offset)], [roundCrt(offset[0]+rightmost+pad/2+crt_offset), roundCrt(offset[1]+ypcb_edge-backcan_height-crt_offset)], [roundCrt(offset[0]+backcan_width/2+crt_offset), roundCrt(offset[1]+ypcb_edge-backcan_height-crt_offset)], [roundCrt(offset[0]+backcan_width/2+crt_offset), roundCrt(offset[1]+ypcb_edge-crt_offset)], [roundCrt(offset[0]+shield_width/2+crt_offset), roundCrt(offset[1]+ypcb_edge-crt_offset)], [roundCrt(offset[0]+shield_width/2+crt_offset), roundCrt(offset[1]+ypcb_edge+shield_thickness+crt_offset)], [roundCrt(offset[0]+can_width/2+crt_offset), roundCrt(offset[1]+ypcb_edge+shield_thickness+crt_offset)], [roundCrt(offset[0]+can_width/2+crt_offset), roundCrt(offset[1]+ypcb_edge+shield_thickness+can_height+crt_offset)], [roundCrt(offset[0]-can_width/2-crt_offset), roundCrt(offset[1]+ypcb_edge+shield_thickness+can_height+crt_offset)], ], layer='F.CrtYd', width=lw_crt)) # add model kicad_mod.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0,0,0], scale=[1,1,1], rotate=[0,0,0])) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') ================================================ FILE: scripts/tools/footprint_scripts_pin_headers.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * # NOQA from math import sqrt crt_offset = 0.5 # different for connectors txt_offset = 1 slk_offset = 0.11 def makePinHeadStraight(rows, cols, rm, coldist, package_width, overlen_top, overlen_bottom, ddrill, pad, tags_additional=[], lib_name="Pin_Headers", classname="Pin_Header", classname_description="pin header", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], model3d_path_prefix="${KISYS3DMOD}", isSocket=False): h_fab = (rows - 1) * rm + overlen_top + overlen_bottom w_fab = package_width l_fab = (coldist * (cols - 1) - w_fab) / 2 t_fab = -overlen_top h_slk = h_fab + 2 * slk_offset w_slk = max(w_fab + 2 * slk_offset, coldist * (cols - 1) - pad[0] - 4 * slk_offset) l_slk = (coldist * (cols - 1) - w_slk) / 2 t_slk = -overlen_top - slk_offset w_crt = max(package_width, coldist * (cols - 1) + pad[0]) + 2 * crt_offset h_crt = max(h_fab, (rows - 1) * rm + pad[1]) + 2 * crt_offset l_crt = coldist * (cols - 1) / 2 - w_crt / 2 t_crt = (rows - 1) * rm / 2 - h_crt / 2 text_size = w_fab*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 # if rm == 2.54: # footprint_name = "Pin_Header_Straight_{0}x{1:02}".format(cols, rows) # else: footprint_name = "{3}_Straight_{0}x{1:02}_Pitch{2:03.2f}mm".format(cols, rows, rm,classname) description = "Through hole straight {3}, {0}x{1:02}, {2:03.2f}mm pitch".format(cols, rows, rm,classname_description) tags = "Through hole {3} THT {0}x{1:02} {2:03.2f}mm".format(cols, rows, rm,classname_description) if (cols == 1): description = description + ", single row" tags = tags + " single row" elif (cols == 2): description = description + ", double rows" tags = tags + " double row" elif (cols == 3): description = description + ", triple rows" tags = tags + " triple row" elif (cols == 4): description = description + ", quadruple rows" tags = tags + " quadruple row" if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset=[0,0] if isSocket and cols>1: offset = [-coldist, 0] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append( Text(type='reference', text='REF**', at=[coldist * (cols - 1) / 2, t_slk - txt_offset], layer='F.SilkS')) kicad_modg.append( Text(type='user', text='%R', at=[rm/2*(cols-1), t_crt + offset[1] + (h_crt/2)], rotation=90, layer='F.Fab', size=text_size ,thickness=text_t)) kicad_modg.append( Text(type='value', text=footprint_name, at=[coldist * (cols - 1) / 2, t_slk + h_slk + txt_offset], layer='F.Fab')) # create FAB-layer chamfer = w_fab/4 kicad_modg.append(Line(start=[l_fab + chamfer, t_fab], end=[l_fab + w_fab, t_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab + w_fab, t_fab], end=[l_fab + w_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab + w_fab, t_fab+h_fab], end=[l_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab, t_fab+h_fab], end=[l_fab, t_fab+chamfer], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab, t_fab+chamfer], end=[l_fab + chamfer, t_fab], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer + pin1 marker # Silkscreen body body_min_x_square = pad[0]/2+min_pad_distance+slk_offset body_min_y_square = pad[1]/2+min_pad_distance+slk_offset #drawin bottom line if (rows-1)*rm + body_min_y_square < t_slk + h_slk: kicad_modg.append(Line(start=[l_slk, t_slk + h_slk], end=[l_slk + w_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) else: if rows == 1: kicad_modg.append(Line(start=[l_slk, body_min_y_square], end=[l_slk + w_slk, body_min_y_square], layer='F.SilkS', width=lw_slk)) else: body_min_x_round = sqrt(((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset) - (overlen_bottom+slk_offset) * (overlen_bottom+slk_offset))) kicad_modg.append(Line(start=[l_slk, t_slk + h_slk], end=[-body_min_x_round, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[(cols-1)*coldist+body_min_x_round, t_slk + h_slk], end=[l_slk + w_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) for x in range(0, (cols-1)): kicad_modg.append(Line(start=[x*coldist+body_min_x_round, t_slk + h_slk], end=[(x+1)*coldist-body_min_x_round, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) #drawin sidelines #calculate top Y positon if rm < body_min_y_square*2: shoulder_y_pos = body_min_y_square shoulder_y_lines = 2 else: shoulder_y_pos = rm/2 shoulder_y_lines = 1 if coldist < body_min_x_square*2: top_x_pos = body_min_x_square top_x_lines = 2 else: top_x_pos = coldist/2 top_x_lines = 1 if l_slk + w_slk > body_min_x_square+(cols-1)*coldist: kicad_modg.append(Line(start=[l_slk, shoulder_y_pos], end=[l_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) if cols == 1: kicad_modg.append(Line(start=[l_slk + w_slk, shoulder_y_pos], end=[l_slk + w_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(Line(start=[l_slk + w_slk, t_slk], end=[l_slk + w_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) elif rows != 1: body_min_y_round = sqrt(((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset) - l_slk * l_slk)) kicad_modg.append(Line(start=[l_slk, shoulder_y_pos], end=[l_slk, rm-body_min_y_round], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk, (rows-1)*rm+body_min_y_round], end=[l_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) if cols == 1: kicad_modg.append(Line(start=[l_slk + w_slk, shoulder_y_pos], end=[l_slk + w_slk, rm-body_min_y_round], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(Line(start=[l_slk + w_slk, body_min_y_square], end=[l_slk + w_slk, rm-body_min_y_round], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk + w_slk, (rows-1)*rm+body_min_y_round], end=[l_slk + w_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) for x in range(1, (rows-1)): kicad_modg.append(Line(start=[l_slk, x*rm+body_min_y_round], end=[l_slk, (x+1)*rm-body_min_y_round], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk + w_slk, x*rm+body_min_y_round], end=[l_slk + w_slk, (x+1)*rm-body_min_y_round], layer='F.SilkS', width=lw_slk)) #drawin top if cols == 1: if shoulder_y_lines == 1: kicad_modg.append(Line(start=[l_slk, shoulder_y_pos], end=[l_slk + w_slk, shoulder_y_pos], layer='F.SilkS', width=lw_slk)) elif shoulder_y_lines == 2: top_x_round = sqrt(((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset) - (shoulder_y_pos-rm) * (shoulder_y_pos-rm))) kicad_modg.append(Line(start=[l_slk, shoulder_y_pos], end=[l_slk + w_slk/2-top_x_round, shoulder_y_pos], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk + w_slk/2 + top_x_round, shoulder_y_pos], end=[l_slk + w_slk, shoulder_y_pos], layer='F.SilkS', width=lw_slk)) else: if shoulder_y_lines == 1: kicad_modg.append(Line(start=[l_slk, shoulder_y_pos], end=[top_x_pos, shoulder_y_pos], layer='F.SilkS', width=lw_slk)) elif shoulder_y_lines == 2: top_x_round = sqrt(((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset) - (shoulder_y_pos-rm) * (shoulder_y_pos-rm))) if top_x_pos > coldist-top_x_round: top_x_end = coldist-top_x_round else: top_x_end = top_x_pos kicad_modg.append(Line(start=[l_slk, shoulder_y_pos], end=[-top_x_round, shoulder_y_pos], layer='F.SilkS', width=lw_slk)) if top_x_round*2 + lw_slk*2 < pad[0]: kicad_modg.append(Line(start=[top_x_round, shoulder_y_pos], end=[top_x_end, shoulder_y_pos], layer='F.SilkS', width=lw_slk)) if top_x_lines == 1: kicad_modg.append(Line(start=[top_x_pos, shoulder_y_pos], end=[top_x_pos, t_slk], layer='F.SilkS', width=lw_slk)) elif top_x_lines == 2: shoulder_y_round = sqrt(((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset) - (coldist-top_x_pos) * (coldist-top_x_pos))) if shoulder_y_pos > rm-shoulder_y_round: shoulder_y_pos = rm-shoulder_y_round if shoulder_y_round*2 + lw_slk*2 < pad[1]: kicad_modg.append(Line(start=[top_x_pos, shoulder_y_pos], end=[top_x_pos, shoulder_y_round], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[top_x_pos, -shoulder_y_round], end=[top_x_pos, t_slk], layer='F.SilkS', width=lw_slk)) #highest horizontal line if abs(t_slk) > body_min_y_square: kicad_modg.append(Line(start=[top_x_pos, t_slk], end=[l_slk + w_slk, t_slk], layer='F.SilkS', width=lw_slk)) else: top_x_round = sqrt(((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset) - (abs(t_slk)) * (abs(t_slk)))) if top_x_pos > coldist-top_x_round + 2*lw_slk: kicad_modg.append(Line(start=[top_x_pos, t_slk], end=[coldist-top_x_round, t_slk], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[coldist+top_x_round, t_slk], end=[l_slk + w_slk, t_slk], layer='F.SilkS', width=lw_slk)) ''' if cols == 1: kicad_modg.append( RectLine(start=[l_slk, 0.5 * rm], end=[l_slk + w_slk, t_slk + h_slk], layer='F.SilkS', width=lw_slk)) else: if isSocket and cols>1: kicad_modg.append(PolygoneLine( polygone=[[l_slk+w_slk, 0.5 * rm], [l_slk+w_slk, t_slk + h_slk], [l_slk , t_slk + h_slk], [l_slk , t_slk], [l_slk+w_slk/2, t_slk], [l_slk+w_slk/2, 0.5 * rm], [l_slk+w_slk, 0.5 * rm]], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(PolygoneLine( polygone=[[l_slk, 0.5 * rm], [l_slk, t_slk + h_slk], [l_slk + w_slk, t_slk + h_slk], [l_slk + w_slk, t_slk], [0.5 * rm, t_slk], [0.5 * rm, 0.5 * rm], [l_slk, 0.5 * rm]], layer='F.SilkS', width=lw_slk)) ''' #pin 1 marker pin1_min = -(pad[0]/2+slk_offset+min_pad_distance) if pin1_min < l_slk: pin1_x = pin1_min else: pin1_x = l_slk if pin1_min < t_slk: pin1_y = pin1_min else: pin1_y = t_slk if isSocket and cols>1: kicad_modg.append(PolygoneLine(polygone=[[pin1_x+w_slk, 0], [pin1_x+w_slk, pin1_y], [pin1_x+w_slk-rm/2, pin1_y]], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(PolygoneLine(polygone=[[pin1_x, 0], [pin1_x, pin1_y], [0, pin1_y]], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_OVAL pad_layers = Pad.LAYERS_THT p = 1 for r in range(1, rows + 1): if isSocket and cols>1: x1=coldist else: x1 = 0 for c in range(1, cols + 1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) else: kicad_modg.append( Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) p = p + 1 if isSocket and cols>1: x1 = x1 - coldist else: x1 = x1 + coldist y1 = y1 + rm # add model kicad_modg.append( Model(filename=model3d_path_prefix + "/" + lib_name + ".3dshapes/" + footprint_name + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name)) def makeIdcHeader(rows, cols, rm, coldist, body_width, overlen_top, overlen_bottom, body_offset, ddrill, pad, mating_overlen, wall_thickness, notch_width, orientation, latching, latch_len=0, latch_width=0, mh_ddrill=0, mh_pad=[0,0], mh_overlen=0, mh_offset=0, mh_number='MP', tags_additional=[], extra_description=False, lib_name="Connector_IDC", classname="IDC-Header", classname_description="IDC box header", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], model3d_path_prefix="${KISYS3DMOD}"): pin_size = 0.64 # square pin side length; this appears to be the same for all connectors so use a fixed internal value mh_present = True if mh_ddrill > 0 and mh_pad[0] > 0 and mh_pad[1] > 0 and mh_overlen > 0 else False mh_y = [-mh_overlen, (rows - 1) * rm + mh_overlen] h_fab = (rows - 1) * rm + overlen_top + overlen_bottom w_fab = body_width l_fab = (coldist * (cols - 1) - w_fab) / 2 if body_offset == 0 else body_offset t_fab = -overlen_top h_slk = h_fab + 2 * slk_offset w_slk = max(w_fab + 2 * slk_offset, coldist * (cols - 1) - pad[0] - 4 * slk_offset) l_slk = (coldist * (cols - 1) - w_slk) / 2 if body_offset == 0 else body_offset t_slk = -overlen_top - slk_offset # these calculations are so tight that new body styles will probably break them h_crt = max(max(h_fab, (rows - 1) * rm + pad[1]) + 2 * latch_len, (rows - 1) * rm + 2 * mh_overlen + mh_pad[1]) + 2 * crt_offset w_crt = max(body_width, coldist * (cols - 1) + pad[0]) + 2 * crt_offset if body_offset <= 0 else pad[0] / 2 + body_offset + body_width + 2 * crt_offset l_crt = l_fab - crt_offset if body_offset <= 0 else -pad[0] / 2 - crt_offset t_crt = min(t_fab - latch_len, -mh_overlen - mh_pad[1] / 2) - crt_offset #if orientation == 'Horizontal' and latching and mh_ddrill > 0: if mh_present and (mh_offset - mh_pad[0] / 2 < l_fab): # horizontal latching with mounting holes is a special case l_crt = mh_offset - mh_pad[0] / 2 - crt_offset w_crt = -l_crt + body_width + body_offset + crt_offset # center of the body (horizontal: middle pin or the center of the middle pins for vertical) center_fab = [coldist * (cols - 1) / 2 if orientation == 'Vertical' else body_offset + body_width / 2, t_fab + h_fab / 2] center_fp = [l_crt + w_crt / 2, center_fab[1]] text_size = w_fab*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 footprint_name = "{3}_{0}x{1:02}{7}_P{2:03.2f}mm{4}{5}_{6}".format(cols, rows, rm, classname, "_Latch" if latching else "", "{0:03.1f}mm".format(latch_len) if latch_len > 0 else "", orientation, "-1MP" if mh_present else "") #footprint_name = footprint_name_base + "_MountHole" if mh_present else footprint_name_base if cols == 1: description_rows = "single row" tags_rows = "single row" elif cols == 2: description_rows = "double rows" tags_rows = "double row" elif cols == 3: description_rows = "triple rows" tags_rows = "triple row" elif cols == 4: description_rows = "quadruple rows" tags_rows = "quadruple row" description = "Through hole {3}, {0}x{1:02}, {2:03.2f}mm pitch, DIN 41651 / IEC 60603-13, {4}{5}{6}{7}".format(cols, rows, rm, classname_description, description_rows, ", {0:03.1f}mm".format(latch_len) if latch_len > 0 else "", " latches" if latching else "", ", mounting holes" if mh_present else "", orientation.lower()) tags = "Through hole {5} {3} THT {0}x{1:02} {2:03.2f}mm {4}".format(cols, rows, rm, classname_description, tags_rows, orientation.lower()) if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t if extra_description: description = description + ", " + extra_description print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # instantiate footprint (SMD origin at center, THT at pin 1) kicad_modg = Footprint(footprint_name) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[center_fp[0], t_crt - text_size[1] / 2], layer='F.SilkS')) kicad_modg.append(Text(type='user', text='%R', at=[center_fab[0], center_fab[1]], rotation=90, layer='F.Fab', size=text_size, thickness=text_t)) kicad_modg.append(Text(type='value', text=footprint_name, at=[center_fp[0], t_crt + h_crt + text_size[1] / 2], layer='F.Fab')) # for shrouded headers, fab and silk layers have very similar geometry # can use the same code to build lines on both layers with slight changes in values between layers # zip together lists with fab and then silk layer settings as the list elements so the same code can draw both layers for layer, line_width, lyr_offset, chamfer in zip(['F.Fab', 'F.SilkS'], [lw_fab, lw_slk], [0, slk_offset], [min(1, w_fab / 4), 0]): # body outline if orientation == 'Horizontal' and latching: # body outline taken from existing KiCad footprint body_polygon = [{'x':body_offset - lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + 6.98 + lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab + 3.17 - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab + 6.99 + lyr_offset}, {'x':l_fab + 12.7 + lyr_offset, 'y':t_fab + 9.14 + lyr_offset}, {'x':l_fab + 12.7 + lyr_offset, 'y':t_fab + h_fab - 9.14 - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab + h_fab - 6.99 - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab + h_fab - 3.17 + lyr_offset}, {'x':l_fab + 6.98 + lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':body_offset - lyr_offset, 'y':t_fab + h_fab + lyr_offset}] # body outline taken from simplified 3M 3000 model (also modify arguments: body_offset=-1.24 and body_width=1.24+15.53) # https://www.3m.com/3M/en_US/company-us/all-3m-products/~/3M-Four-Wall-Header-3000-Series/?N=5002385+3290316872&preselect=8709318+8710652+8733900+8734573&rt=rud body_polygon = [{'x':body_offset - lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + 7.11 + lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + 16.77 + lyr_offset, 'y':t_fab + 3.47 - lyr_offset}, {'x':l_fab + 16.77 + lyr_offset, 'y':t_fab + 7.44 + lyr_offset}, {'x':l_fab + 13.21 + lyr_offset, 'y':t_fab + 8.07 + lyr_offset}, {'x':l_fab + 13.21 + lyr_offset, 'y':t_fab + h_fab - 8.07 - lyr_offset}, {'x':l_fab + 16.77 + lyr_offset, 'y':t_fab + h_fab - 7.44 - lyr_offset}, {'x':l_fab + 16.77 + lyr_offset, 'y':t_fab + h_fab - 3.47 + lyr_offset}, {'x':l_fab + 7.11 + lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':body_offset - lyr_offset, 'y':t_fab + h_fab + lyr_offset}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) # now draw the left side vertical line, which may be broken on the silk layer around mounting holes if layer == 'F.SilkS' and mh_present and mh_pad[0]/2 - mh_offset > -body_offset + slk_offset * 1.5: body_polygon = [{'x':body_offset - lyr_offset, 'y':t_fab - lyr_offset}, {'x':body_offset - lyr_offset, 'y':mh_y[0] - mh_pad[0]/2}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) body_polygon = [{'x':body_offset - lyr_offset, 'y':mh_y[0] + mh_pad[0]/2}, {'x':body_offset - lyr_offset, 'y':mh_y[1] - mh_pad[0]/2}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) body_polygon = [{'x':body_offset - lyr_offset, 'y':mh_y[1] + mh_pad[0]/2}, {'x':body_offset - lyr_offset, 'y':t_fab + h_fab + lyr_offset}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) else: body_polygon = [{'x':body_offset - lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':body_offset - lyr_offset, 'y':t_fab - lyr_offset}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) else: # body outline silk lines need to clear the mounting hole on vertical headers if mh_present and layer == 'F.SilkS': body_polygon = [{'x':mh_offset + mh_pad[0]/2 - lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':mh_offset + mh_pad[0]/2 - lyr_offset, 'y':t_fab + h_fab + lyr_offset}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) body_polygon = [{'x':mh_offset - mh_pad[0]/2 + lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab - lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab - lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':mh_offset - mh_pad[0]/2 + lyr_offset, 'y':t_fab + h_fab + lyr_offset}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) else: body_polygon = [{'x':l_fab + chamfer - lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab - lyr_offset}, {'x':l_fab + w_fab + lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':l_fab - lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':l_fab - lyr_offset, 'y':t_fab + chamfer - lyr_offset}] kicad_mod.append(PolygoneLine(polygone=body_polygon, layer=layer, width=line_width)) if chamfer > 0 and not (orientation == 'Horizontal' and latching): kicad_modg.append(Line(start=[l_fab, t_fab + chamfer], end=[l_fab + chamfer, t_fab], layer=layer, width=line_width)) # vertical mating connector outline (this is the same for both layers) if orientation == 'Vertical': mating_conn_polygon = [{'x':l_fab - lyr_offset, 'y':center_fab[1] - notch_width/2}, {'x':l_fab + wall_thickness, 'y':center_fab[1] - notch_width/2}, {'x':l_fab + wall_thickness, 'y':-mating_overlen}, {'x':l_fab + w_fab - wall_thickness, 'y':-mating_overlen}, {'x':l_fab + w_fab - wall_thickness, 'y':(rows - 1) * rm + mating_overlen}, {'x':l_fab + wall_thickness, 'y':(rows - 1) * rm + mating_overlen}, {'x':l_fab + wall_thickness, 'y':center_fab[1] + notch_width/2}, {'x':l_fab + wall_thickness, 'y':center_fab[1] + notch_width/2}, {'x':l_fab - lyr_offset, 'y':center_fab[1] + notch_width/2}] kicad_mod.append(PolygoneLine(polygone=mating_conn_polygon, layer=layer, width=line_width)) # horizontal mating connector 'notch' lines if orientation == 'Horizontal' and not latching: kicad_modg.append(Line(start=[body_offset - lyr_offset, center_fab[1] - notch_width / 2], end=[l_fab + w_fab + lyr_offset, center_fab[1] - notch_width / 2], layer=layer, width=line_width)) kicad_modg.append(Line(start=[body_offset - lyr_offset, center_fab[1] + notch_width / 2], end=[l_fab + w_fab + lyr_offset, center_fab[1] + notch_width / 2], layer=layer, width=line_width)) # vertical latches (horizontal latches are off the PCB and not shown) if orientation == 'Vertical' and latching and latch_len > 0: # body outline silk lines need to clear the mounting hole on vertical headers if mh_present and layer == 'F.SilkS': # top latch latch_top_polygon = [{'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':mh_y[0] - mh_pad[1]/2 + lyr_offset}, {'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':t_fab - latch_len - lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':t_fab - latch_len - lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':mh_y[0] - mh_pad[1]/2 + lyr_offset}] kicad_mod.append(PolygoneLine(polygone=latch_top_polygon, layer=layer, width=line_width)) # bottom latch latch_bottom_polygon = [{'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':mh_y[1] + mh_pad[1]/2 - lyr_offset}, {'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':t_fab + h_fab + latch_len + lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':t_fab + h_fab + latch_len + lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':mh_y[1] + mh_pad[1]/2 - lyr_offset}] kicad_mod.append(PolygoneLine(polygone=latch_bottom_polygon, layer=layer, width=line_width)) else: # top latch latch_top_polygon = [{'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':t_fab - lyr_offset}, {'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':t_fab - latch_len - lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':t_fab - latch_len - lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':t_fab - lyr_offset}] kicad_mod.append(PolygoneLine(polygone=latch_top_polygon, layer=layer, width=line_width)) # bottom latch latch_bottom_polygon = [{'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':t_fab + h_fab + lyr_offset}, {'x':center_fab[0] - latch_width/2 - lyr_offset, 'y':t_fab + h_fab + latch_len + lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':t_fab + h_fab + latch_len + lyr_offset}, {'x':center_fab[0] + latch_width/2 + lyr_offset, 'y':t_fab + h_fab + lyr_offset}] kicad_mod.append(PolygoneLine(polygone=latch_bottom_polygon, layer=layer, width=line_width)) # horizontal pin outlines (only applies if the body is right of the leftmost pin row) #if orientation == 'Horizontal' and not latching: if body_offset > 0: for row in range(rows): horiz_pin_polygon = [{'x':body_offset, 'y':rm * row - pin_size / 2}, {'x':-pin_size / 2, 'y':rm * row - pin_size / 2}, {'x':-pin_size / 2, 'y':rm * row + pin_size / 2}, {'x':body_offset, 'y':rm * row + pin_size / 2}] kicad_modg.append(PolygoneLine(polygone=horiz_pin_polygon, layer='F.Fab', width=lw_fab)) # silk pin 1 mark (triangle to the left of pin 1) slk_mark_height = 1 slk_mark_width = 1 slk_mark_tip = min(l_fab, -pad[0] / 2) - 0.5 # offset 0.5mm from pin 1 or the body slk_polygon = [{'x':slk_mark_tip, 'y':0}, {'x':slk_mark_tip - slk_mark_width, 'y':-slk_mark_height / 2}, {'x':slk_mark_tip - slk_mark_width, 'y':slk_mark_height / 2}, {'x':slk_mark_tip, 'y':0}] kicad_mod.append(PolygoneLine(polygone=slk_polygon, layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads (first the left row then the right row) for start_pos, initial in zip([0, coldist], range(1, cols + 1)): kicad_modg.append(PadArray(pincount=rows, spacing=[0,rm], start=[start_pos,0], initial=initial, increment=cols, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, size=pad, drill=ddrill, layers=Pad.LAYERS_THT)) # create mounting hole pads if mh_present: for mh_y_offset in mh_y: kicad_modg.append(Pad(number=mh_number, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[mh_offset, mh_y_offset], size=mh_pad, drill=mh_ddrill, layers=Pad.LAYERS_THT)) # add model (even if there are mounting holes on the footprint do not include that in the 3D model) kicad_modg.append(Model(filename="{0}/{1}.3dshapes/{2}.wrl".format(model3d_path_prefix, lib_name, footprint_name), at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name)) # # <-->pack_offset # <------->pack_width # <------------------------------>pin_length # <-coldist> # +--- +-------+ # | OOO OOO | +-------------------------------+ ^ # | OOO ==== OOO | | + ^ pin_width # OOO OOO | +-------------------------------+ | v # +-------+ rm # OOO OOO | +-------------------------------+ | # OOO ==== OOO | | + v # OOO OOO | +-------------------------------+ # +-------+ rm # def makePinHeadAngled(rows, cols, rm, coldist, pack_width, pack_offset, pin_length, pin_width, ddrill, pad, tags_additional=[], lib_name="Pin_Headers", classname="Pin_Header", classname_description="pin header", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], model3d_path_prefix="${KISYS3DMOD}"): h_fabb = (rows - 1) * rm + rm / 2 + rm / 2 w_fabb = pack_width l_fabb = coldist * (cols - 1) + pack_offset t_fabb = -rm / 2 l_fabp = l_fabb + w_fabb t_fabp = -pin_width / 2 text_size = w_fabb*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 h_slkb = h_fabb + 2 * slk_offset w_slkb = w_fabb + 2 * slk_offset l_slkb = l_fabb - slk_offset t_slkb = t_fabb - slk_offset l_slkp = l_slkb + w_slkb t_slkp = t_fabp - slk_offset l_slk = -rm / 2 t_slk = -rm / 2 body_lines_y = False w_crt = rm / 2 + (cols - 1) * coldist + pack_offset + pack_width + pin_length + 2 * crt_offset h_crt = h_fabb + 2 * crt_offset l_crt = -rm / 2 - crt_offset t_crt = -rm / 2 - crt_offset # if rm == 2.54: # footprint_name = "Pin_Header_Angled_{0}x{1:02}".format(cols, rows) # else: footprint_name = "{3}_Angled_{0}x{1:02}_Pitch{2:03.2f}mm".format(cols, rows, rm, classname) description = "Through hole angled {4}, {0}x{1:02}, {2:03.2f}mm pitch, {3}mm pin length".format(cols, rows, rm, pin_length, classname_description) tags = "Through hole angled {3} THT {0}x{1:02} {2:03.2f}mm".format(cols, rows, rm, classname_description) if (cols == 1): description = description + ", single row" tags = tags + " single row" elif (cols == 2): description = description + ", double rows" tags = tags + " double row" elif (cols == 3): description = description + ", triple rows" tags = tags + " triple row" if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset = [0, 0] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append( Text(type='reference', text='REF**', at=[l_crt + w_crt / 2, t_crt + crt_offset - txt_offset], layer='F.SilkS')) kicad_modg.append( Text(type='user', text='%R', at=[l_fabb + (w_fabb/2), t_crt + offset[1] + (h_crt/2)], rotation=90, layer='F.Fab', size=text_size ,thickness=text_t)) kicad_modg.append( Text(type='value', text=footprint_name, at=[l_crt + w_crt / 2, t_crt + h_crt - crt_offset + txt_offset], layer='F.Fab')) # create FAB-layer chamfer = w_fabb/4 kicad_modg.append(Line(start=[l_fabb + chamfer, t_fabb], end=[l_fabb + w_fabb, t_fabb], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fabb + w_fabb, t_fabb], end=[l_fabb + w_fabb, t_fabb+rm*rows], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fabb + w_fabb, t_fabb+rm*rows], end=[l_fabb, t_fabb+rm*rows], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fabb, t_fabb+rm*rows], end=[l_fabb, t_fabb+chamfer], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fabb, t_fabb+chamfer], end=[l_fabb + chamfer, t_fabb], layer='F.Fab', width=lw_fab)) y1 = t_fabb yp = t_fabp for r in range(1, rows + 1): kicad_modg.append(Line(start=[-pin_width/2, yp], end=[l_fabb, yp], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-pin_width/2, yp], end=[-pin_width/2, yp + pin_width], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-pin_width/2, yp + pin_width], end=[l_fabb, yp + pin_width], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fabb + w_fabb, yp], end=[l_fabp + pin_length, yp], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fabp + pin_length, yp], end=[l_fabp + pin_length, yp + pin_width], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fabb + w_fabb, yp + pin_width], end=[l_fabp + pin_length, yp + pin_width], layer='F.Fab', width=lw_fab)) y1 = y1 + rm yp = yp + rm # create SILKSCREEN-layer + pin1 marker #calculate point to avoid collision with pad clearance pin_line_x = sqrt(((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset) - (pin_width/2+slk_offset) * (pin_width/2+slk_offset))) # Silkscreen body body_min_x_square = pad[0]/2+min_pad_distance+slk_offset body_min_y_square = pad[1]/2+min_pad_distance+slk_offset if rm/2 < body_min_y_square: body_min_x_round = sqrt((((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset)) - (rm/2 * rm/2))) if l_slkb > body_min_x_round + (cols-1)*coldist and l_slkb < body_min_x_square +(cols-1)*coldist: body_lines_y = sqrt((((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset)) - ((l_slkb-(cols-1)*coldist) * (l_slkb-(cols-1)*coldist)))) else: body_min_x_round = 0 if rm/2+slk_offset < body_min_y_square: bodyend_min_x_round = sqrt((((pad[0]/2+min_pad_distance+slk_offset) * (pad[0]/2+min_pad_distance+slk_offset)) - ((rm/2+slk_offset) * (rm/2+slk_offset)))) else: bodyend_min_x_round = 0 # if body is starting outside the pads if l_slkb-slk_offset > pad[0]/2 + min_pad_distance + (cols-1)*coldist: kicad_modg.append(RectLine(start=[l_slkb, t_slkb], end=[l_slkp, t_slkb+rm*rows+slk_offset*2], layer='F.SilkS', width=lw_slk)) else: if l_slkb < body_min_x_square + (cols-1)*coldist and t_slkb-slk_offset > -(body_min_y_square + (cols-1)*coldist): if cols == 1: upper_body_x = body_min_x_square else: upper_body_x = bodyend_min_x_round + (cols-1)*coldist else: upper_body_x = l_slkb if rows == 1 and cols == 1: lower_body_x = body_min_x_square + (cols-1)*coldist elif l_slkb < bodyend_min_x_round + (cols-1)*coldist and t_slkb-slk_offset > -(body_min_y_square + (cols-1)*coldist): lower_body_x = bodyend_min_x_round + (cols-1)*coldist else: lower_body_x = l_slkb if body_lines_y != False: if cols == 1: kicad_modg.append(PolygoneLine(polygone=[[upper_body_x, t_slkb], [l_slkp, t_slkb], [l_slkp, t_slkb+rm*rows+slk_offset*2], [lower_body_x, t_slkb+rm*rows+slk_offset*2],[lower_body_x, t_slkb+rm*rows-rm/2+slk_offset+body_lines_y]], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(PolygoneLine(polygone=[[upper_body_x, -body_lines_y],[upper_body_x, t_slkb], [l_slkp, t_slkb], [l_slkp, t_slkb+rm*rows+slk_offset*2], [lower_body_x, t_slkb+rm*rows+slk_offset*2],[lower_body_x, t_slkb+rm*rows-rm/2+slk_offset+body_lines_y]], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(PolygoneLine(polygone=[[upper_body_x, t_slkb], [l_slkp, t_slkb], [l_slkp, t_slkb+rm*rows+slk_offset*2], [lower_body_x, t_slkb+rm*rows+slk_offset*2]], layer='F.SilkS', width=lw_slk)) for r in range(0, rows): if r != 0: if r == 1 and rm/2 < body_min_y_square and cols == 1: if l_slkb < body_min_x_square: kicad_modg.append(Line(start=[body_min_x_square, (r-1)*rm+rm/2], end=[l_slkp, (r-1)*rm+rm/2], layer='F.SilkS',width=lw_slk)) else: kicad_modg.append(Line(start=[l_slkb, (r-1)*rm+rm/2], end=[l_slkp, (r-1)*rm+rm/2], layer='F.SilkS',width=lw_slk)) else: # add line between rows if l_slkb < body_min_x_round + (cols-1)*coldist: kicad_modg.append(Line(start=[body_min_x_round+ (cols-1)*coldist, (r-1)*rm+rm/2], end=[l_slkp, (r-1)*rm+rm/2], layer='F.SilkS',width=lw_slk)) else: kicad_modg.append(Line(start=[l_slkb, (r-1)*rm+rm/2], end=[l_slkp, (r-1)*rm+rm/2], layer='F.SilkS',width=lw_slk)) if body_lines_y != False: kicad_modg.append(Line(start=[l_slkb, (r-1)*rm+body_lines_y], end=[l_slkb, (r)*rm-body_lines_y], layer='F.SilkS',width=lw_slk)) # pin kicad_modg.append(PolygoneLine(polygone=[[l_slkp, r*rm-pin_width/2-slk_offset], [l_slkp + pin_length, r*rm-pin_width/2-slk_offset], [l_slkp + pin_length, r*rm+pin_width/2+slk_offset],[l_slkp, r*rm+pin_width/2+slk_offset]], layer='F.SilkS', width=lw_slk)) # color the first pin if r == 0: y = -(pin_width/2) while y < pin_width/2: kicad_modg.append(Line(start=[l_slkp, y], end=[l_slkp + pin_length, y], layer='F.SilkS', width=lw_slk)) y += lw_slk # if body is starting at the pads if l_slkb-slk_offset > pad[0]/2 + min_pad_distance + (cols-1)*coldist: if r == 0 and cols == 1: #add the lines between pads and silkscreenbody kicad_modg.append(Line(start=[pad[0]/2+min_pad_distance+slk_offset, r*rm-pin_width/2-slk_offset], end=[l_slkb, r*rm-pin_width/2-slk_offset], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[pad[0]/2+min_pad_distance+slk_offset, r*rm+pin_width/2+slk_offset], end=[l_slkb, r*rm+pin_width/2+slk_offset], layer='F.SilkS', width=lw_slk)) else: #add the lines between pads and silkscreenbody kicad_modg.append(Line(start=[(cols-1)*coldist + pin_line_x, r*rm-pin_width/2-slk_offset], end=[l_slkb, r*rm-pin_width/2-slk_offset], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[(cols-1)*coldist + pin_line_x, r*rm+pin_width/2+slk_offset], end=[l_slkb, r*rm+pin_width/2+slk_offset], layer='F.SilkS', width=lw_slk)) if cols > 1: for c in range(1, cols): #add the lines between pads start_point_x = (c-1)*coldist+pin_line_x end_point_x = c*coldist-pin_line_x if start_point_x < end_point_x - lw_slk: if r == 0 and c == 1: kicad_modg.append(Line(start=[pad[0]/2+min_pad_distance+slk_offset, r*rm-pin_width/2-slk_offset], end=[end_point_x, r*rm-pin_width/2-slk_offset], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[pad[0]/2+min_pad_distance+slk_offset, r*rm+pin_width/2+slk_offset], end=[end_point_x, r*rm+pin_width/2+slk_offset], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(Line(start=[start_point_x, r*rm-pin_width/2-slk_offset], end=[end_point_x, r*rm-pin_width/2-slk_offset], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[start_point_x, r*rm+pin_width/2+slk_offset], end=[end_point_x, r*rm+pin_width/2+slk_offset], layer='F.SilkS', width=lw_slk)) # pin 1 marker pin1_min = -(pad[0]/2+slk_offset+min_pad_distance) if pin1_min < l_slk: pin1_x = pin1_min else: pin1_x = l_slk if pin1_min < t_slk: pin1_y = pin1_min else: pin1_y = t_slk kicad_modg.append(PolygoneLine(polygone=[[pin1_x, 0], [pin1_x, pin1_y], [0, pin1_y]], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_OVAL pad_layers = Pad.LAYERS_THT p = 1 for r in range(1, rows + 1): x1 = 0 for c in range(1, cols + 1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) else: kicad_modg.append( Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) p = p + 1 x1 = x1 + coldist y1 = y1 + rm # add model kicad_modg.append( Model(filename=model3d_path_prefix + "/" + lib_name + ".3dshapes/" + footprint_name + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name)) # # <-->pack_offset # <--------------pack_width---------------> # <-coldist> # +---------------------------------------+ ---+ # | | OOO OOO | ^ # | | OOO ==== OOO | ^ pin_width # | | OOO OOO | v # +---------------------------------------+ rm # | | OOO OOO | # | | OOO ==== OOO v # | | OOO OOO # +---------------------------------------+ # def makeSocketStripAngled(rows, cols, rm, coldist, pack_width, pack_offset, pin_width, ddrill, pad, tags_additional=[], lib_name="$Socket_Strips", classname="Socket_Strip", classname_description="socket strip", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], model3d_path_prefix="${KISYS3DMOD}"): h_fabb = (rows - 1) * rm + rm / 2 + rm / 2 w_fabb = -pack_width l_fabb = -1*(coldist * (cols - 1) + pack_offset) t_fabb = -rm / 2 l_fabp = l_fabb + w_fabb t_fabp = -pin_width / 2 h_slkb = cc_fabb + 2 * slk_offset w_slkb = w_fabb - 2 * slk_offset l_slkb = l_fabb + slk_offset t_slkb = t_fabb - slk_offset l_slkp = l_slkb + w_slkb t_slkp = t_fabp - slk_offset l_slk = -rm / 2 t_slk = -rm / 2 w_crt = -1*(rm / 2 + (cols - 1) * coldist + pack_offset + pack_width + 2 * crt_offset) h_crt = h_fabb + 2 * crt_offset l_crt = rm / 2 + crt_offset t_crt = -rm / 2 - crt_offset # if rm == 2.54: # footprint_name = "Pin_Header_Angled_{0}x{1:02}".format(cols, rows) # else: footprint_name = "{3}_Angled_{0}x{1:02}_Pitch{2:03.2f}mm".format(cols, rows, rm, classname) description = "Through hole angled {4}, {0}x{1:02}, {2:03.2f}mm pitch, {3}mm socket length".format(cols, rows, rm, pack_width, classname_description) tags = "Through hole angled {3} THT {0}x{1:02} {2:03.2f}mm".format(cols, rows, rm, classname_description) if (cols == 1): description = description + ", single row" tags = tags + " single row" elif (cols == 2): description = description + ", double rows" tags = tags + " double row" elif (cols == 3): description = description + ", triple rows" tags = tags + " triple row" if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset = [0, 0] kicad_modg =Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append( Text(type='reference', text='REF**', at=[l_crt + w_crt / 2, t_crt + crt_offset - txt_offset], layer='F.SilkS')) kicad_modg.append( Text(type='user', text='%R', at=[l_crt + w_crt / 2, t_crt + crt_offset - txt_offset], layer='F.Fab')) kicad_modg.append( Text(type='value', text=footprint_name, at=[l_crt + w_crt / 2, t_crt + h_crt - crt_offset + txt_offset], layer='F.Fab')) # create FAB-layer y1 = t_fabb yp = t_fabp for r in range(1, rows + 1): kicad_modg.append(RectLine(start=[l_fabb, y1], end=[l_fabb + w_fabb, y1 + rm], layer='F.Fab', width=lw_fab)) kicad_modg.append( RectLine(start=[0, yp], end=[l_fabb , yp + pin_width], layer='F.Fab', width=lw_fab)) y1 = y1 + rm yp = yp + rm # create SILKSCREEN-layer + pin1 marker y1 = t_slkb yp = t_slkp for r in range(1, rows + 1): if (rows == 1 and r == 1): kicad_modg.append( RectLine(start=[l_slkb, y1], end=[l_slkp, y1 + rm + 2 * slk_offset], layer='F.SilkS', width=lw_slk)) if (r == 1 or r == rows): kicad_modg.append(RectLine(start=[l_slkb, y1], end=[l_slkp, y1 + rm + slk_offset], layer='F.SilkS', width=lw_slk)) y1 = y1 + slk_offset else: kicad_modg.append(RectLine(start=[l_slkb, y1], end=[l_slkp, y1 + rm], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[-1*((cols - 1) * coldist + pad[0] / 2 + slk_offset+lw_slk), yp], end=[l_slkb, yp], layer='F.SilkS',width=lw_slk)) kicad_modg.append(Line(start=[-1*((cols - 1) * coldist + pad[0] / 2 + slk_offset+lw_slk), yp + pin_width + 2 * slk_offset],end=[l_slkb, yp + pin_width + 2 * slk_offset], layer='F.SilkS', width=lw_slk)) if cols > 1: for c in range(2, cols + 1): kicad_modg.append(Line(start=[-1*((c - 2) * coldist + pad[0] / 2 + slk_offset+lw_slk), yp], end=[-1*((c - 1) * coldist - pad[0] / 2 - slk_offset-lw_slk), yp], layer='F.SilkS', width=lw_slk)) kicad_modg.append( Line(start=[-1*((c - 2) * coldist + pad[0] / 2 + slk_offset+lw_slk), yp + pin_width + 2 * slk_offset], end=[-1*((c - 1) * coldist - pad[0] / 2 - slk_offset-lw_slk), yp + pin_width + 2 * slk_offset], layer='F.SilkS', width=lw_slk)) if r == 1: y = y1 + lw_slk while y < y1 + rm + 2 * slk_offset: kicad_modg.append(Line(start=[l_slkb, y], end=[l_slkp, y], layer='F.SilkS', width=lw_slk)) y = y + lw_slk y1 = y1 + rm yp = yp + rm kicad_modg.append(PolygoneLine(polygone=[[0, -rm/2], [rm/2, -rm/2], [rm/2, 0]], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_OVAL pad_layers = Pad.LAYERS_THT p = 1 for r in range(1, rows + 1): x1 = 0 for c in range(1, cols + 1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) else: kicad_modg.append( Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) p = p + 1 x1 = x1 - coldist y1 = y1 + rm # add model kicad_modg.append( Model(filename=model3d_path_prefix + "/" + lib_name + ".3dshapes/" + footprint_name + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name)) def makePinHeadStraightSMD(rows, cols, rm, coldist, rmx_pad_offset,rmx_pin_length, pin_width, package_width, overlen_top, overlen_bottom, pad, start_left=True, tags_additional=[], lib_name="$Pin_Headers", classname="Pin_Header", classname_description="pin header", offset3d=[0, 0, 0], scale3d=[1, 1, 1], rotate3d=[0, 0, 0], model3d_path_prefix="${KISYS3DMOD}", isSocket=False): ddrill=0.5 h_fab = (rows - 1) * rm + overlen_top + overlen_bottom w_fab = package_width l_fab = (coldist * (cols - 1) - w_fab) / 2 t_fab = -overlen_top h_slk = h_fab + 2 * slk_offset w_slk = max(w_fab + 2 * slk_offset, coldist * (cols - 1) - pad[0] - 4 * slk_offset) l_slk = (coldist * (cols - 1) - w_slk) / 2 t_slk = -overlen_top - slk_offset w_crt = max(package_width, coldist * (cols - 1)+2*rmx_pad_offset + pad[0]) + 2 * crt_offset h_crt = max(h_fab, (rows - 1) * rm + pad[1]) + 2 * crt_offset l_crt = coldist * (cols - 1) / 2 - w_crt / 2 t_crt = (rows - 1) * rm / 2 - h_crt / 2 # if rm == 2.54: # footprint_name = "Pin_Header_Straight_{0}x{1:02}".format(cols, rows) # else: footprint_name = "{3}_Straight_{0}x{1:02}_Pitch{2:03.2f}mm_SMD".format(cols, rows, rm,classname) description = "surface-mounted straight {3}, {0}x{1:02}, {2:03.2f}mm pitch".format(cols, rows, rm,classname_description) tags = "Surface mounted {3} SMD {0}x{1:02} {2:03.2f}mm".format(cols, rows, rm,classname_description) if (cols == 1): description = description + ", single row" tags = tags + " single row" if start_left: description = description + ", style 1 (pin 1 left)" tags = tags + " style1 pin1 left" footprint_name = footprint_name + "_Pin1Left" else: description = description + ", style 2 (pin 1 right)" tags = tags + " style2 pin1 right" footprint_name = footprint_name + "_Pin1Right" elif (cols == 2): description = description + ", double rows" tags = tags + " double row" if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_mod.setAttribute('smd') # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset = [-(cols-1)*coldist/2, -(rows-1)*rm/2.0] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append( Text(type='reference', text='REF**', at=[coldist * (cols - 1) / 2, t_slk - txt_offset], layer='F.SilkS')) kicad_modg.append( Text(type='user', text='%R', at=[rm/2*(cols-1),(rows-1)*rm/2.0], rotation=90, layer='F.Fab')) kicad_modg.append( Text(type='value', text=footprint_name, at=[coldist * (cols - 1) / 2, t_slk + h_slk + txt_offset], layer='F.Fab')) cleft = range(0, rows, 2) cright = range(1, rows, 2) if not start_left: cleft = range(1, rows, 2) cright = range(0, rows, 2) # create FAB-layer chamfer = (rm-pin_width)/2 kicad_modg.append(Line(start=[l_fab + w_fab, t_fab+h_fab], end=[l_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) if start_left == True: kicad_modg.append(Line(start=[l_fab + chamfer, t_fab], end=[l_fab + w_fab, t_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab, t_fab+h_fab], end=[l_fab, t_fab+chamfer], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab, t_fab+chamfer], end=[l_fab + chamfer, t_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab + w_fab, t_fab], end=[l_fab + w_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) else: kicad_modg.append(Line(start=[l_fab, t_fab], end=[l_fab + w_fab - chamfer, t_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab + w_fab, t_fab+h_fab], end=[l_fab + w_fab, t_fab+chamfer], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab + w_fab, t_fab+chamfer], end=[l_fab + w_fab - chamfer, t_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab, t_fab], end=[l_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) if cols==1: for c in cleft: kicad_modg.append(Line(start=[l_fab, c*rm-pin_width/2], end=[-rmx_pin_length, c*rm-pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-rmx_pin_length, c*rm-pin_width/2], end=[-rmx_pin_length, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-rmx_pin_length, c*rm+pin_width/2], end=[l_fab, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) for c in cright: kicad_modg.append(Line(start=[l_fab + w_fab, c*rm-pin_width/2], end=[rmx_pin_length, c*rm-pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[rmx_pin_length, c*rm-pin_width/2], end=[rmx_pin_length, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[rmx_pin_length, c*rm+pin_width/2], end=[l_fab + w_fab, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) elif cols == 2: for c in range(0,rows): kicad_modg.append(Line(start=[l_fab, c*rm-pin_width/2], end=[-rmx_pin_length+rm/2, c*rm-pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-rmx_pin_length+rm/2, c*rm-pin_width/2], end=[-rmx_pin_length+rm/2, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[-rmx_pin_length+rm/2, c*rm+pin_width/2], end=[l_fab, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[l_fab + w_fab, c*rm-pin_width/2], end=[rm/2+rmx_pin_length, c*rm-pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[rm/2+rmx_pin_length, c*rm-pin_width/2], end=[rm/2+rmx_pin_length, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[rm/2+rmx_pin_length, c*rm+pin_width/2], end=[l_fab + w_fab, c*rm+pin_width/2], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer + pin1 marker slk_offset_pad = pad[1]/2+slk_offset+min_pad_distance kicad_modg.append(Line(start=[l_slk, t_slk], end=[l_slk + w_slk, t_slk], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk, t_slk+h_slk], end=[l_slk + w_slk, t_slk+h_slk], layer='F.SilkS', width=lw_slk)) if cols == 1: for c in cleft: if c == 0: kicad_modg.append(Line(start=[l_slk , -slk_offset_pad], end=[-rmx_pad_offset-pad[0]/2+lw_slk/2 , -slk_offset_pad], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk , t_slk], end=[l_slk, -slk_offset_pad], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk+w_slk, (rows-1)*rm+slk_offset_pad],end=[l_slk+w_slk, t_slk+h_slk],layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk+w_slk, -slk_offset_pad], end=[l_slk+w_slk, min(t_slk+h_slk,(c+1) * rm - slk_offset_pad)], layer='F.SilkS', width=lw_slk)) elif c == rows-1: kicad_modg.append(Line(start=[l_slk+w_slk, max(t_slk, (c-1) * rm + slk_offset_pad)], end=[l_slk+w_slk, t_slk+h_slk], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(Line(start=[l_slk+w_slk, max(t_slk, (c-1) * rm + slk_offset_pad)], end=[l_slk+w_slk, min(t_slk+h_slk,(c+1) * rm - slk_offset_pad)], layer='F.SilkS', width=lw_slk)) for c in cright: if c == 0: kicad_modg.append(Line(start=[l_slk+w_slk, -slk_offset_pad],end=[rmx_pad_offset+pad[0]/2-lw_slk/2, -slk_offset_pad],layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk+w_slk, t_slk],end=[l_slk+w_slk, -slk_offset_pad],layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk, (rows-1)*rm+slk_offset_pad],end=[l_slk, t_slk+h_slk],layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk , -slk_offset_pad],end=[l_slk, min(t_slk+h_slk,(c+1) * rm - slk_offset_pad)], layer='F.SilkS',width=lw_slk)) if c == rows-1: kicad_modg.append(Line(start=[l_slk , max(t_slk, (c-1) * rm + slk_offset_pad)],end=[l_slk, t_slk+h_slk], layer='F.SilkS',width=lw_slk)) else: kicad_modg.append(Line(start=[l_slk , max(t_slk, (c-1) * rm + slk_offset_pad)],end=[l_slk, min(t_slk+h_slk,(c+1) * rm - slk_offset_pad)], layer='F.SilkS',width=lw_slk)) if (cols==2): if isSocket: #print(pad[0]/2+rmx_pad_offset,pad[0]/2,rmx_pad_offset) kicad_modg.append(Line(start=[pad[0]/2+rmx_pad_offset+coldist, -(pad[1] / 2 + 2*lw_slk + slk_offset)], end=[l_slk+w_slk, -(pad[1] / 2 + 2*lw_slk + slk_offset)], layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(Line(start=[-rmx_pad_offset+rm/2-pad[0]/2+lw_slk/2, -slk_offset_pad], end=[l_slk, -slk_offset_pad], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk , t_slk], end=[l_slk, -slk_offset_pad], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk+w_slk , t_slk], end=[l_slk+w_slk, -slk_offset_pad], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk, (rows-1)*rm+slk_offset_pad],end=[l_slk, t_slk+h_slk],layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk+w_slk, (rows-1)*rm+slk_offset_pad],end=[l_slk+w_slk, t_slk+h_slk],layer='F.SilkS', width=lw_slk)) if slk_offset_pad*2 < rm - lw_slk*2: for c in range(0,rows-1): kicad_modg.append(Line(start=[l_slk, c*rm+slk_offset_pad],end=[l_slk, (c+1)*rm-slk_offset_pad],layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk+w_slk, c*rm+slk_offset_pad],end=[l_slk+w_slk, (c+1)*rm-slk_offset_pad],layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_SMT pad_shape1 = Pad.SHAPE_RECT pad_layers = Pad.LAYERS_SMT if cols==1: for c in cleft: kicad_modg.append(Pad(number=c+1, type=pad_type, shape=pad_shape1, at=[-rmx_pad_offset, c*rm], size=pad, drill=ddrill,layers=pad_layers)) for c in cright: kicad_modg.append(Pad(number=c+1, type=pad_type, shape=pad_shape1, at=[rmx_pad_offset, c * rm], size=pad, drill=ddrill,layers=pad_layers)) elif cols==2: p = 1 for c in range(0,rows): if isSocket: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[rm/2+rmx_pad_offset, c * rm], size=pad, drill=ddrill,layers=pad_layers)) p=p+1 kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[-rmx_pad_offset+rm/2, c * rm], size=pad, drill=ddrill, layers=pad_layers)) p=p+1 else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[-rmx_pad_offset+rm/2, c * rm], size=pad, drill=ddrill, layers=pad_layers)) p=p+1 kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[rmx_pad_offset+rm/2, c * rm], size=pad, drill=ddrill,layers=pad_layers)) p=p+1 # add model kicad_modg.append( Model(filename=model3d_path_prefix + "/" + lib_name + ".3dshapes/" + footprint_name + ".wrl", at=offset3d, scale=scale3d, rotate=rotate3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file output_dir = '{lib_name:s}.pretty/'.format(lib_name=lib_name) if not os.path.isdir(output_dir): #returns false if path does not yet exist!! (Does not check path validity) os.makedirs(output_dir) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile('{outdir:s}{fp_name:s}.kicad_mod'.format(outdir=output_dir, fp_name=footprint_name)) ================================================ FILE: scripts/tools/footprint_scripts_potentiometers.py ================================================ #!/usr/bin/env python import sys import os import math import argparse # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_global_properties import * ''' An external argument interface is provided. It should be used to make footprints part-by-part as needed. Only minimal testing and error checking provided! Separate scripts are provided to make "off the shelf" pots using these functions. See make_Potentiometer_SMD.py and make_Potentiomter_THT.py ''' def makePotentiometerHorizontal(class_name="", wbody=0, hbody=0, dscrew=0, style="normal", ddrill=0, wscrew=0, wshaft=0, dshaft=0, pinxoffset=0, pinyoffset=0, pins=3, R_POW=0, x_3d=[0, 0, 0], s_3d=[1, 1, 1], r_3d=[0, 0, 0], has3d=1, rmx=5.08, rmy=5.08, specialtags=[], add_description="", lib_name="Potentiometer", name_additions=[], script3d="", height3d=10, screwzpos=5, mh_ddrill=1.5, mh_count=0, mh_rmx=0, mh_rmy=15, mh_xoffset=0, mh_yoffset=0): """ create potentiometer footprints, horizontally mounted style="normal": ^ ^ +-----------+ pinyoffset | | | v | ^ | O1 O4 +-------+ ^ | rmy | | +-------------------------------+ ^ | | v | O2 O5 | | | dshaft | | | | +-------------------------------+ v dscrew hbody | O3 O6 +-------+ v | | | v +-----------+ <----------wshaft---------------> <------->wscrew <---wbody---> <->pinxoffset style="trimmer" (only valid for 3-pin!!!): O1 ^ rmy O2 v O3 <-rmx--> Parameters: class_name: manufacturer and MPN like "Bourns 3214W" (str) wbody: body length (float) hbody: body height (float) wscrew: collar length (float) dscrew: collar diameter (float) wshaft: shaft length (float) dshaft: shaft diameter (float) style: type of pot from "normal" or "trimmer" [default = "normal"] (str) pinxoffset: distance from face of body to first column of pins [default = 0] (float) pinyoffset: distance from top of body to first row of pins [default = 0] (float) pins: number of pins; "trimmer" style can only support 3 pins [default = 3] (int) rmx: column spacing of pins [default = 5.08] (float) rmy: row (or vertical) spacing of pins [default = 5.08] (float) ddrill: drill hole diameter [default = 1.5] (float) R_POW: power rating of pot with zero being default [default = 0] (float) x_3d: 3D model location [default = [0, 0, 0]] (list of floats) s_3d: 3D model scaling [default = [1 / 2.54, 1 / 2.54, 1 / 2.54]] (list of floats) r_3d: 3D model rotation [default = [0, 0, 0]] (list of floats) has3d: presence of 3D model [default = 1] (bool) specialtags: keywords that will be comma-delimited [default = []] (list of strs) add_description: descriptive text [default = ""] (str) lib_name: library name [default = "Potentiometers"] (str) name_additions: extra text for footprint name that will be underscore-delimited [default = []] (list of strs) script3d: script to kick off 3D model generation in FreeCad [default = ""] (str) height3d: height of 3D model [default = 10] (float) screwzpos: height of collar above bottom of body [default = 5] (float) mh_ddrill: drill hole diameter of mounting holes [default = 1.5] (float) mh_count: number of mounting holes; 1, 2, or 4 are supported [default = 0] (int) mh_rmx: column spacing of mounting holes [default = 0] (float) mh_rmy: row spacing of mounting holes [default = 15] (float) mh_xoffset: distance from face of body to first column of mounting holes [default = 0] (float) mh_yoffset: distance from top of body to first row of mounting holes [default = 0] (float) Returns: None """ padx = 1.8 * ddrill pady = padx txt_offset = 1 slk_offset = 0.12 grid_crt = 0.01 pad1style = Pad.SHAPE_CIRCLE cols = pins / 3 overpadwidth = rmx * (cols - 1) + padx overpadheight = rmy * 2 + pady # generate list of pads depending on pin count padpos = [] offset = [0, 0] if pins >= 3: # for 3 pins, pot could be normal with a vertical column of pins or a trimmer with staggered pins if style=="trimmer": padpos.append([3, 0, 2 * rmy, ddrill, padx, pady]) padpos.append([2, rmx, rmy, ddrill, padx, pady]) padpos.append([1, 0, 0, ddrill, padx, pady]) offset = [0, 0] else: padpos.append([3, 0, 0, ddrill, padx, pady]) padpos.append([2, 0, rmy, ddrill, padx, pady]) padpos.append([1, 0, 2 * rmy, ddrill, padx, pady]) offset = [0, -2 * rmy] if pins >= 6: padpos.append([6, -rmx, 0, ddrill, padx, pady]) padpos.append([5, -rmx, rmy, ddrill, padx, pady]) padpos.append([4, -rmx, 2 * rmy, ddrill, padx, pady]) if pins >= 9: padpos.append([9, -2*rmx, 0, ddrill, padx, pady]) padpos.append([8, -2*rmx, rmy, ddrill, padx, pady]) padpos.append([7, -2*rmx, 2 * rmy, ddrill, padx, pady]) # add mounting holes to list of pads if mh_count == 1: padpos.append(['', mh_xoffset, -mh_yoffset, mh_ddrill, 2 * mh_ddrill, 2 * mh_ddrill]) if mh_count == 2: padpos.append(['', mh_xoffset, -mh_yoffset, mh_ddrill, 2 * mh_ddrill, 2 * mh_ddrill]) padpos.append(['', mh_xoffset - mh_rmx, -mh_yoffset + mh_rmy, mh_ddrill, 2 * mh_ddrill, 2 * mh_ddrill]) if mh_count == 4: padpos.append(['', mh_xoffset, -mh_yoffset, mh_ddrill, 2 * mh_ddrill, 2 * mh_ddrill]) padpos.append(['', mh_xoffset - mh_rmx, -mh_yoffset + mh_rmy, mh_ddrill, 2 * mh_ddrill, 2 * mh_ddrill]) padpos.append(['', mh_xoffset - mh_rmx, -mh_yoffset, mh_ddrill, 2 * mh_ddrill, 2 * mh_ddrill]) padpos.append(['', mh_xoffset, -mh_yoffset + mh_rmy, mh_ddrill, 2 * mh_ddrill, 2 * mh_ddrill]) lbody_fab = -(wbody - pinxoffset) # left side of body tbody_fab = -pinyoffset # top of body wbody_fab = wbody # body length hbody_fab = hbody # body height wscrew_fab = wscrew # collar length hscrew_fab = dscrew # collar height lscrew_fab = lbody_fab + wbody_fab # left side of collar tscrew_fab = tbody_fab + (hbody_fab - hscrew_fab) / 2.0 # top of collar wshaft_fab = wshaft # shaft length hshaft_fab = dshaft # shaft diameter lshaft_fab = lscrew_fab + wscrew_fab # left side of shaft tshaft_fab = tbody_fab + (hbody_fab - hshaft_fab) / 2.0 # top of shaft lbody_slk = lbody_fab - math.copysign(slk_offset, wbody_fab) tbody_slk = tbody_fab - slk_offset wbody_slk = wbody_fab + math.copysign(2 * slk_offset, wbody_fab) hbody_slk = hbody_fab + 2 * slk_offset lscrew_slk = lbody_slk + wbody_slk tscrew_slk = tscrew_fab - slk_offset wscrew_slk = wscrew_fab hscrew_slk = hscrew_fab + 2 * slk_offset lshaft_slk = lscrew_slk + wscrew_slk tshaft_slk = tshaft_fab - slk_offset wshaft_slk = wshaft_fab hshaft_slk = hshaft_fab + 2 * slk_offset if wbody_fab < 0: wscrew_slk = wscrew_slk + 2 * slk_offset wshaft_slk = wshaft_slk + 2 * slk_offset minx = miny = 1e99 maxx = maxy = -1e99 for p in padpos: maxx = max(maxx, p[1] + p[4] / 2) minx = min(minx, p[1] - p[4] / 2) maxy = max(maxy, p[2] + p[5] / 2) miny = min(miny, p[2] - p[5] / 2) minx = min(minx, lbody_fab, lbody_fab + wbody_fab + wscrew_fab + wshaft_fab) miny = min(miny, tbody_fab, tscrew_fab, tshaft_fab) maxx = max(maxx, lbody_fab + wbody_fab + wscrew_fab + wshaft_fab, lbody_fab) maxy = max(maxy, tbody_fab + hbody_fab, tscrew_fab + hscrew_fab, tshaft_fab + hshaft_fab) h_crt = (maxy - miny) + 2 * crt_offset w_crt = (maxx - minx) + 2 * crt_offset l_crt = minx - crt_offset t_crt = miny - crt_offset pow_rat = "" if R_POW > 0: pow_rat = "{0}W".format(R_POW) if (1 / R_POW == int(1 / R_POW)): pow_rat = pow_rat + " = 1/{0}W".format(int(1 / R_POW)) tgs = specialtags print tgs print class_name tgs.append(class_name) if len(pow_rat) > 0: tgs.append(pow_rat) description = "Potentiometer, horizontal" tags = "Potentiometer horizontal" for t in tgs: description = description + ", " + t tags = tags + " " + t description = description + ", " + add_description footprint_name = "" for n in name_additions: footprint_name = footprint_name + "_" + n footprint_name = lib_name + "_" + "_".join(class_name.split()) + "_Horizontal" print(footprint_name) if script3d != "": with open(script3d, "a") as myfile: myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("App.ActiveDocument.clearAll()\n") line=0 line += 1; script3d_writevariable(myfile, line, 'lbody_fab', min(lbody_fab+wbody_fab,lbody_fab)+offset[0]) line += 1; script3d_writevariable(myfile, line, 'tbody_fab', min(tbody_fab+hbody_fab,tbody_fab)+offset[1]) line += 1; script3d_writevariable(myfile, line, 'wbody_fab', math.fabs(wbody_fab)) line += 1; script3d_writevariable(myfile, line, 'hbody_fab', math.fabs(hbody_fab)) line += 1; script3d_writevariable(myfile, line, 'lscrew_fab', min(lscrew_fab+wscrew_fab,lscrew_fab)+offset[0]) line += 1; script3d_writevariable(myfile, line, 'tscrew_fab', min(tscrew_fab+hscrew_fab,tscrew_fab)+offset[1]) line += 1; script3d_writevariable(myfile, line, 'wscrew_fab', math.fabs(wscrew_fab)) line += 1; script3d_writevariable(myfile, line, 'hscrew_fab', math.fabs(hscrew_fab)) line += 1; script3d_writevariable(myfile, line, 'lshaft_fab', min(lshaft_fab+wshaft_fab,lshaft_fab)+offset[0]) line += 1; script3d_writevariable(myfile, line, 'tshaft_fab', min(tshaft_fab+hshaft_fab,tshaft_fab)+offset[1]) line += 1; script3d_writevariable(myfile, line, 'wshaft_fab', math.fabs(wshaft_fab)) line += 1; script3d_writevariable(myfile, line, 'hshaft_fab', math.fabs(hshaft_fab)) line += 1; script3d_writevariable(myfile, line, 'rmx', rmx) line += 1; script3d_writevariable(myfile, line, 'rmy', rmy) for p in padpos: if p[0]==1: line += 1; script3d_writevariable(myfile, line, 'padx', p[1]) line += 1; script3d_writevariable(myfile, line, 'pady', p[2]) line += 1; script3d_writevariable(myfile, line, 'd_wire', ddrill-0.3) line += 1; script3d_writevariable(myfile, line, 'height', height3d) line += 1; script3d_writevariable(myfile, line, 'screwzpos', screwzpos) written=False for p in padpos: if p[0] == 0 and not written: line += 1; script3d_writevariable(myfile, line, 'mhpadx', p[1]) line += 1; script3d_writevariable(myfile, line, 'mhpady', p[2]) written=True line += 1; script3d_writevariable(myfile, line, 'mh_rmx', mh_rmx) line += 1; script3d_writevariable(myfile, line, 'mh_rmy', mh_rmy) line += 1; script3d_writevariable(myfile, line, 'offsetx', offset[0]) line += 1; script3d_writevariable(myfile, line, 'offsety', offset[1]) myfile.write("App.ActiveDocument.recompute()\n\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format(footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[0, t_crt - txt_offset], layer='F.SilkS')) kicad_modg.append(Text(type='value', text=footprint_name, at=[0, t_crt + h_crt + txt_offset], layer='F.Fab')) # create FAB-layer # horizontal pot: place refdes on F.Fab in center of body and shrink size if body is small text_size = min(1, abs(round(wbody_fab / 4.5, 2))) kicad_modg.append(Text(type='user', text='%R', at=[lbody_fab+wbody_fab/2.0, tbody_fab+hbody_fab/2.0], size=[text_size, text_size], layer='F.Fab')) kicad_modg.append(RectLine(start=[lbody_fab, tbody_fab], end=[lbody_fab + wbody_fab, tbody_fab + hbody_fab], layer='F.Fab',width=lw_fab)) if wscrew_fab * hscrew_fab != 0: kicad_modg.append( RectLine(start=[lscrew_fab, tscrew_fab], end=[lscrew_fab + wscrew_fab, tscrew_fab + hscrew_fab],layer='F.Fab', width=lw_fab)) if wshaft_fab * hshaft_fab != 0: kicad_modg.append( RectLine(start=[lshaft_fab, tshaft_fab], end=[lshaft_fab + wshaft_fab, tshaft_fab + hshaft_fab],layer='F.Fab', width=lw_fab)) # build keepout for silkscreen keepouts = [] for p in padpos: keepouts = keepouts + addKeepoutRound(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) # create SILKSCREEN-layer addRectWithKeepout(kicad_modg, lbody_slk, tbody_slk, wbody_slk, hbody_slk, 'F.SilkS', lw_slk, keepouts, 0.001) if wscrew>0 and wscrew_slk * hscrew_slk != 0: addRectWithKeepout(kicad_modg, lscrew_slk, tscrew_slk, wscrew_slk, hscrew_slk, 'F.SilkS', lw_slk, keepouts,0.001) if wshaft>0 and wshaft_slk * hshaft_slk != 0: addRectWithKeepout(kicad_modg, lshaft_slk, tshaft_slk, wshaft_slk, hshaft_slk, 'F.SilkS', lw_slk, keepouts,0.001) # create courtyard kicad_mod.append(RectLine(start=[roundG(l_crt + offset[0], grid_crt), roundG(t_crt + offset[1], grid_crt)], end=[roundG(l_crt + w_crt + offset[0], grid_crt), roundG(t_crt + h_crt + offset[1], grid_crt)],layer='F.CrtYd', width=lw_crt)) # create pads for p in padpos: ps = Pad.SHAPE_CIRCLE if p[0] == 1: ps = pad1style kicad_modg.append(Pad(number=p[0], type=Pad.TYPE_THT, shape=ps, at=[p[1], p[2]], size=[p[4], p[5]], drill=p[3], layers=['*.Cu', '*.Mask'])) # add model if (has3d != 0): kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + "_THT.3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') def makePotentiometerVertical(class_name, wbody, hbody, screwstyle="none", style="normal", d_body=0, dshaft=6, dscrew=7, c_ddrill=0, c_offsetx=0, c_offsety=0, pinxoffset=0, pinyoffset=0, pins=3, rmx=5.08, rmy=5.08, ddrill=1.5, shaft_hole=False, SMD_pads=False, SMD_padsize=[], SMD_type="3-5", R_POW=0, x_3d=[0, 0, 0], s_3d=[1, 1, 1], r_3d=[0, 0, 0], has3d=1, specialtags=[], add_description="", lib_name="Potentiometer", name_additions=[], script3d="", height3d=10, mh_ddrill=1.5, mh_count=0, mh_rmx=0, mh_rmy=15, mh_xoffset=0, mh_yoffset=0, mh_smd=False, mh_padsize=[], mh_nopads=False): """ create potentiometer footprints, vertically mounted style=normal <-->pinxoffset ^ ^ +---------------+ ^ pinyoffset | | | | v | ^ O1 | | cofsety | rmy | CCCCC | | | v O2 | CCCCC | v | | CCCCC | hbody O3 | | | | | v +---------------+ <------->coffsetx <-----wbody-----> style=trimmer (only valid for 3-pin!!!) O1 ^ rmy O2 v O3 <-rmx--> Parameters: class_name: manufacturer and MPN like "Bourns 3214W" (str) wbody: body length (float) hbody: body height (float) screwstyle: screw style from "none", "slit", or "cross" [default = "none"] (str) style: type of pot from "normal" or "trimmer" [default = "normal"] (str) d_body: diameter of body for circular pot [default = 0] (float) dshaft: shaft diameter [default = 6] (float) dscrew: collar diameter [default = 7] (float) c_ddrill: drill diameter to fit collar or zero for no hole [default = 0] (float) c_offsetx: distance from left side of body to collar center [default = 0] (float) c_offsety:: distance from top of body to collar center [default = 0] (float) pinxoffset: distance from left side of body to first column of pins [default = 0] (float) pinyoffset: distance from top of body to first row of pins [default = 0] (float) pins: number of pins; "trimmer" style can only support 3 pins [default = 3] (int) rmx: column spacing of pins [default = 5.08] (float) rmy: row (or vertical) spacing of pins [default = 5.08] (float) ddrill: drill hole diameter [default = 1.5] (float) shaft_hole: places hole under pot for shaft through PCB [default = False] (bool) SMD_pads: allows using SMD pads [default = False] (bool) SMD_padsize: X and Y dimensions of SMD pads in [X, Y] format [default = []] (list of floats) SMD_type: allow specifying the SMD pad layout from below options [default = "3-5"] (str) "3-5": 5 pin pot with 3 pins on left side and 2 pins on right side with no middle pin R_POW: power rating of pot with zero being default [default = 0] (float) x_3d: 3D model location [default = [0, 0, 0]] (list of floats) s_3d: 3D model scaling [default = [1 / 2.54, 1 / 2.54, 1 / 2.54]] (list of floats) r_3d: 3D model rotation [default = [0, 0, 0]] (list of floats) has3d: presence of 3D model [default = 1] (bool) specialtags: keywords that will be comma-delimited [default = []] (list of strs) add_description: descriptive text [default = ""] (str) lib_name: library name [default = "Potentiometers"] (str) name_additions: extra text for footprint name that will be underscore-delimited [default = []] (list of strs) script3d: script to kick off 3D model generation in FreeCad [default = ""] (str) height3d: height of 3D model [default = 10] (float) mh_ddrill: drill hole diameter of mounting holes [default = 1.5] (float) mh_count: number of mounting holes; 1, 2, or 4 are supported [default = 0] (int) mh_rmx: column spacing of mounting holes [default = 0] (float) mh_rmy: row spacing of mounting holes [default = 15] (float) mh_xoffset: distance from left side of body to first column of mounting holes [default = 0] (float) mh_yoffset: distance from top of body to first row of mounting holes [default = 0] (float) mh_smd: allows using SMD mounting holes [default = False] (bool) mh_padsize: X and Y dimensions of SMD mounting holes in [X, Y] format [default = []] (list of floats) mh_nopads: allows selecting the presence of mounting holes [default = False] (bool) Returns: None """ padx = 1.8 * ddrill pady = padx if SMD_pads and len(SMD_padsize) >= 2: padx = SMD_padsize[0] pady = SMD_padsize[1] txt_offset = 1 slk_offset = 0.12 grid_crt = 0.01 pad1style = Pad.SHAPE_CIRCLE cols = pins / 3 overpadwidth = rmx * (cols - 1) + padx overpadheight = rmy * 2 + pady padpos = [] offset = [0, 0] padtype = Pad.TYPE_THT padstyle = Pad.SHAPE_CIRCLE if SMD_pads: padtype = Pad.TYPE_SMT padstyle = Pad.SHAPE_RECT mhtype = Pad.TYPE_NPTH mhstyle = Pad.SHAPE_CIRCLE if mh_smd: mhtype = Pad.TYPE_SMT mhstyle = Pad.SHAPE_RECT if pins >= 3: if style == "trimmer": padpos.append([3, 0, 0, ddrill, padx, pady, padtype, padstyle]) padpos.append([2, rmx, rmy, ddrill, padx, pady, padtype, padstyle]) padpos.append([1, 0, 2 * rmy, ddrill, padx, pady, padtype, padstyle]) offset = [0, -2 * rmy] if SMD_pads: offset = [-rmx/2.0, -rmy] else: padpos.append([3, 0, 0, ddrill, padx, pady, padtype, padstyle]) padpos.append([2, 0, rmy, ddrill, padx, pady, padtype, padstyle]) padpos.append([1, 0, 2 * rmy, ddrill, padx, pady, padtype, padstyle]) offset = [0, -2 * rmy] if SMD_pads: offset = [0, -rmy] if pins == 4: padpos.append([4, 0, -rmy, ddrill, padx, pady, padtype, padstyle]) if pins == 5 and SMD_pads and SMD_type == "3-5": padpos.append([5, -rmx / 2.0 + rmx + pinxoffset, 0, ddrill, padx, pady, padtype, padstyle]) padpos.append([4, -rmx / 2.0 + rmx + pinxoffset, 2 * rmy, ddrill, padx, pady, padtype, padstyle]) if SMD_pads: offset[0] = -rmx / 2.0 if pins >= 6: padpos.append([6, -rmx, 0, ddrill, padx, pady, padtype, padstyle]) padpos.append([5, -rmx, rmy, ddrill, padx, pady, padtype, padstyle]) padpos.append([4, -rmx, 2 * rmy, ddrill, padx, pady, padtype, padstyle]) if SMD_pads: offset[0] = -rmx / 2.0 if pins >= 9: padpos.append([9, -2 * rmx, 0, ddrill, padx, pady, padtype, padstyle]) padpos.append([8, -2 * rmx, rmy, ddrill, padx, pady, padtype, padstyle]) padpos.append([7, -2 * rmx, 2 * rmy, ddrill, padx, pady, padtype, padstyle]) if SMD_pads: offset[0] = -rmx mhpadsizex = 2 * mh_ddrill mhpadsizey = mhpadsizex if mh_nopads: mhpadsizex = mh_ddrill mhpadsizey = mhpadsizex if mh_smd and len(mh_padsize) >= 2: mhpadsizex = mh_padsize[0] mhpadsizey = mh_padsize[1] if mh_count == 1: padpos.append(['', mh_xoffset, -mh_yoffset, mh_ddrill, mhpadsizex, mhpadsizey, mhtype, mhstyle]) if mh_count == 2: padpos.append(['', mh_xoffset, -mh_yoffset, mh_ddrill, mhpadsizex, mhpadsizey, mhtype, mhstyle]) padpos.append(['', mh_xoffset - mh_rmx, -mh_yoffset + mh_rmy, mh_ddrill, mhpadsizex, mhpadsizey, mhtype, mhstyle]) if mh_count == 4: padpos.append(['', mh_xoffset, -mh_yoffset, mh_ddrill, mhpadsizex, mhpadsizey, mhtype, mhstyle]) padpos.append(['', mh_xoffset - mh_rmx, -mh_yoffset + mh_rmy, mh_ddrill, mhpadsizex, mhpadsizey, mhtype, mhstyle]) padpos.append(['', mh_xoffset - mh_rmx, -mh_yoffset, mh_ddrill, mhpadsizex, mhpadsizey, mhtype, mhstyle]) padpos.append(['', mh_xoffset, -mh_yoffset + mh_rmy, mh_ddrill, mhpadsizex, mhpadsizey, mhtype, mhstyle]) lbody_fab = pinxoffset # why does the X offset of the pin set the body's left side location?!?!?! tbody_fab = -pinyoffset wbody_fab = wbody hbody_fab = hbody cdbody_fab = d_body clbody_fab = lbody_fab + c_offsetx ctbody_fab = tbody_fab + c_offsety if c_ddrill > 0 and shaft_hole == True: padpos.append(['', clbody_fab, ctbody_fab, c_ddrill, c_ddrill, c_ddrill, mhtype, mhstyle]) lbody_slk = lbody_fab - slk_offset tbody_slk = tbody_fab - slk_offset wbody_slk = wbody_fab + 2 * slk_offset hbody_slk = hbody_fab + 2 * slk_offset cdbody_slk = cdbody_fab + 2 * slk_offset clbody_slk = clbody_fab ctbody_slk = ctbody_fab minx = miny = 1e99 maxx = maxy = -1e99 for p in padpos: maxx = max(maxx, p[1] + p[4] / 2) minx = min(minx, p[1] - p[4] / 2) maxy = max(maxy, p[2] + p[5] / 2) miny = min(miny, p[2] - p[5] / 2) minx = min(minx, lbody_fab, clbody_fab - cdbody_fab / 2) miny = min(miny, tbody_fab, ctbody_fab - cdbody_fab / 2) maxx = max(maxx, lbody_fab + wbody_fab, clbody_fab + cdbody_fab / 2) maxy = max(maxy, tbody_fab + hbody_fab, ctbody_fab + cdbody_fab / 2) h_crt = (maxy - miny) + 2 * crt_offset w_crt = (maxx - minx) + 2 * crt_offset l_crt = minx - crt_offset t_crt = miny - crt_offset pow_rat = "" if R_POW > 0: pow_rat = "{0}W".format(R_POW) if (1 / R_POW == int(1 / R_POW)): pow_rat = pow_rat + " = 1/{0}W".format(int(1 / R_POW)) tgs = specialtags tgs.append(class_name) if len(pow_rat) > 0: tgs.append(pow_rat) description = "Potentiometer, vertical" tags = "Potentiometer vertical" if shaft_hole: description = description + ", shaft hole" tags = tags + " hole" for t in tgs: description = description + ", " + t tags = tags + " " + t description = description + ", " + add_description for n in name_additions: footprint_name = footprint_name + "_" + n footprint_name = lib_name + "_" + "_".join(class_name.split()) + "_Vertical" if shaft_hole: footprint_name = footprint_name + "_Hole" print(footprint_name) if script3d != "": with open(script3d, "a") as myfile: myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("App.ActiveDocument.clearAll()\n") line = 0 line += 1; script3d_writevariable(myfile, line, 'lbody_fab', min(lbody_fab+wbody_fab,lbody_fab)+offset[0]) line += 1; script3d_writevariable(myfile, line, 'tbody_fab', min(tbody_fab+hbody_fab,tbody_fab)+offset[1]) line += 1; script3d_writevariable(myfile, line, 'wbody_fab', math.fabs(wbody_fab)) line += 1; script3d_writevariable(myfile, line, 'hbody_fab', math.fabs(hbody_fab)) line += 1; script3d_writevariable(myfile, line, 'clbody_fab', clbody_fab+offset[0]) line += 1; script3d_writevariable(myfile, line, 'ctbody_fab', ctbody_fab+offset[1]) line += 1; script3d_writevariable(myfile, line, 'cdbody_fab', cdbody_fab) line += 1; script3d_writevariable(myfile, line, 'dscrew', dscrew) line += 1; script3d_writevariable(myfile, line, 'dshaft', dshaft) line += 1; script3d_writevariable(myfile, line, 'rmx', rmx) line += 1; script3d_writevariable(myfile, line, 'rmy', rmy) for p in padpos: if p[0] == 1: line += 1; script3d_writevariable(myfile, line, 'padx', p[1]) line += 1; script3d_writevariable(myfile, line, 'pady', p[2]) line += 1; script3d_writevariable(myfile, line, 'd_wire', ddrill-0.3) line += 1; script3d_writevariable(myfile, line, 'height', height3d) written=False for p in padpos: if p[0] == 0 and not written: line += 1; script3d_writevariable(myfile, line, 'mhpadx', p[1]) line += 1; script3d_writevariable(myfile, line, 'mhpady', p[2]) written=True line += 1; script3d_writevariable(myfile, line, 'mh_rmx', mh_rmx) line += 1; script3d_writevariable(myfile, line, 'mh_rmy', mh_rmy) line += 1; script3d_writevariable(myfile, line, 'offsetx', offset[0]) line += 1; script3d_writevariable(myfile, line, 'offsety', offset[1]) myfile.write("App.ActiveDocument.recompute()\n\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format(footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) if SMD_pads: kicad_mod.setAttribute('smd') kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[l_crt + w_crt / 2, t_crt - txt_offset], layer='F.SilkS')) kicad_modg.append(Text(type='value', text=footprint_name, at=[l_crt + w_crt / 2, t_crt + h_crt + txt_offset], layer='F.Fab')) # create FAB-layer drawbody = wbody > 0 if cdbody_fab > 0: if style == "trimmer": dy = hbody_fab / 2.0 if drawbody and dy <= cdbody_fab / 2: dx = math.sqrt(cdbody_fab * cdbody_fab / 4 - dy * dy) alpha = 360 - 2 * math.atan(dy / dy) / 3.1415 * 180 kicad_modg.append(PolygoneLine(polygone=[[clbody_fab - dx, ctbody_fab - dy],[lbody_fab, ctbody_fab - dy], [lbody_fab, ctbody_fab + dy],[clbody_fab - dx, ctbody_fab + dy]], layer='F.Fab', width=lw_fab)) kicad_modg.append(Arc(center=[clbody_fab, ctbody_fab], start=[clbody_fab-dx, ctbody_fab-dy], angle=alpha,layer='F.Fab', width=lw_fab)) else: kicad_modg.append(Circle(center=[clbody_fab, ctbody_fab], radius=cdbody_fab / 2.0, layer='F.Fab', width=lw_fab)) # vertical trimmer with circular body: place refdes on F.Fab inside # calculate text size (also used for offset distance inside outer circle) text_size = min(1, round((cdbody_fab - dscrew) / 4.0, 2)) kicad_modg.append(Text(type='user', text='%R', at=[clbody_fab - cdbody_fab / 2.0 + text_size * 1.2, ctbody_fab], size=[text_size, text_size], layer='F.Fab', rotation = 90)) if drawbody: kicad_modg.append(RectLine(start=[lbody_fab, tbody_fab], end=[lbody_fab + wbody_fab, tbody_fab + hbody_fab], layer='F.Fab', width=lw_fab)) else: cdradius = cdbody_fab / 2.0 kicad_modg.append(Circle(center=[clbody_fab, ctbody_fab], radius=cdradius, layer='F.Fab', width=lw_fab)) dy = hbody_fab / 2.0 #kicad_modg.append(Text(type='user', text='REF**', at=[clbody_fab, ctbody_fab], size=[min(1.0, cdradius), min(1.0, cdradius)], layer='F.Fab')) if drawbody and dy <= cdbody_fab / 2.0: dx = math.sqrt(cdbody_fab * cdbody_fab / 4 - dy * dy) # vertical pot with circular body: place refdes on F.Fab inside left edge of body kicad_modg.append(Text(type='user', text='%R', at=[lbody_fab + 1, ctbody_fab], layer='F.Fab', rotation = 90)) kicad_modg.append(PolygoneLine(polygone=[[clbody_fab - dx, ctbody_fab - dy],[lbody_fab, ctbody_fab - dy], [lbody_fab, ctbody_fab + dy],[clbody_fab - dx, ctbody_fab + dy]], layer='F.Fab', width=lw_fab)) elif drawbody: kicad_modg.append(RectLine(start=[lbody_fab, tbody_fab], end=[lbody_fab + wbody_fab, tbody_fab + hbody_fab], layer='F.Fab', width=lw_fab)) elif drawbody: # vertical pot with square body: place refdes on F.Fab inside left edge of body kicad_modg.append(Text(type='user', text='%R', at=[lbody_fab + 1, ctbody_fab], layer='F.Fab', rotation = 90)) kicad_modg.append(RectLine(start=[lbody_fab, tbody_fab], end=[lbody_fab + wbody_fab, tbody_fab + hbody_fab], layer='F.Fab', width=lw_fab)) if dscrew > 0: #kicad_modg.append(Circle(center=[clbody_fab, ctbody_fab], radius=dscrew / 2.0, layer='F.Fab', width=lw_fab)) if screwstyle == "slit": addSlitScrew(kicad_modg, clbody_fab, ctbody_fab, dscrew / 2.0, 'F.Fab', lw_fab) elif screwstyle == "cross": addCrossScrew(kicad_modg, clbody_fab, ctbody_fab, dscrew / 2.0, 'F.Fab', lw_fab) if dshaft > 0 and shaft_hole == False: kicad_modg.append(Circle(center=[clbody_fab, ctbody_fab], radius=dshaft / 2.0, layer='F.Fab', width=lw_fab)) # build keepout for silkscreen keepouts = [] for p in padpos: if p[7] == Pad.SHAPE_CIRCLE: keepouts = keepouts + addKeepoutRound(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) else: keepouts = keepouts + addKeepoutRect(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) # debug_draw_keepouts(kicad_modg,keepouts) # create SILKSCREEN-layer drawbody = wbody > 0 if cdbody_fab > 0: addCircleWithKeepout(kicad_modg, clbody_slk, ctbody_slk, cdbody_slk / 2.0, 'F.SilkS', lw_slk, keepouts) dy = hbody_slk / 2.0 if drawbody and dy <= cdbody_slk / 2.0: dx = math.sqrt(cdbody_slk * cdbody_slk / 4.0 - dy * dy) addHLineWithKeepout(kicad_modg, clbody_slk - dx, lbody_slk, ctbody_slk - dy, 'F.SilkS', lw_slk,keepouts) addVLineWithKeepout(kicad_modg, lbody_slk, ctbody_slk - dy, ctbody_slk + dy, 'F.SilkS', lw_slk,keepouts) addHLineWithKeepout(kicad_modg, clbody_slk - dx, lbody_slk, ctbody_slk + dy, 'F.SilkS', lw_slk,keepouts) drawbody = False if drawbody: addRectWithKeepout(kicad_modg, lbody_slk, tbody_slk, wbody_slk, hbody_slk, 'F.SilkS', lw_slk, keepouts,0.001) # create courtyard kicad_mod.append(RectLine(start=[roundG(l_crt + offset[0], grid_crt), roundG(t_crt + offset[1], grid_crt)], end=[roundG(l_crt + w_crt + offset[0], grid_crt), roundG(t_crt + h_crt + offset[1], grid_crt)], layer='F.CrtYd', width=lw_crt)) # create pads for p in padpos: if p[6] == Pad.TYPE_SMT: kicad_modg.append(Pad(number=p[0], type=p[6], shape=p[7], at=[p[1], p[2]], size=[p[4], p[5]], drill=p[3], layers=['F.Cu', 'F.Paste', 'F.Mask'])) else: kicad_modg.append(Pad(number=p[0], type=p[6], shape=p[7], at=[p[1], p[2]], size=[p[4], p[5]], drill=p[3], layers=['*.Cu', '*.Mask'])) # add model if (has3d != 0): if SMD_pads: kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + "_SMD.3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) else: kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + "_THT.3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') def makeSpindleTrimmer(class_name, wbody, hbody, pinxoffset, pinyoffset, rmx2, rmy2, rmx3, rmy3, dscrew, ddrill=1, wscrew=0, screwxoffset=0, screwyoffset=0, style = "screwleft", screwstyle="slit", shaft_hole=False, SMD_pads=False, SMD_padsize=[], R_POW=0, x_3d=[0, 0, 0], s_3d=[1, 1, 1], r_3d=[0, 0, 0], has3d=1, specialtags=[], add_description="", lib_name="Potentiometer", name_additions=[], script3d="", height3d=10): """ create spindle trimmer potentiometer (only valid for 3-pin!!!) <-----------rmx2-------------> screwxoffset<> <------------------rmx3----------------------> screwyoffset ^ +---------------------------------------------------------------+ ^ ^ | ^ +----| | | | v dsrew +-- | O2O | ^ | pinyoffset v +----| | rmy2 | | wscrew<--->| O3O O1O | v hbody v | | | +---------------------------------------------------------------+ v <----------------------------wbody------------------------------> <------pinxoffset------------------------------------> Parameters: class_name: manufacturer and MPN like "Bourns 3214W" (str) wbody: body length (float) hbody: body height (float) pinxoffset: distance from left side of body to pin 1 (float) pinyoffset: distance from top of body to pin 1 (float) rmx2: distance from pin 1 left to pin 2 (float) rmy2: distance from pin 1 up to pin 2 (float) rmx3: distance from pin 1 left to pin 3 (float) rmy3: distance from pin 1 up to pin 3 (float) dscrew: screw diameter (float) ddrill: drill hole diameter [default = 1] (float) wscrew: length of screw for left screw types [default = 0] (float) screwxoffset: distance from left side of body to screw for top screw types [default = 0] (float) screwyoffset: distance from top of body to center of screw [default = 0] (float) style: location of screw from "screwleft" or "screwtop" [default = "screwleft"] (str) screwstyle: screw style from "slit" or "cross" [default = "slit"] (str) SMD_pads: allows using SMD pads [default = False] (bool) SMD_padsize: X and Y dimensions of SMD pads in [X, Y] format [default = []] (list of floats) R_POW: power rating of pot with zero being default [default = 0] (float) x_3d: 3D model location [default = [0, 0, 0]] (list of floats) s_3d: 3D model scaling [default = [1 / 2.54, 1 / 2.54, 1 / 2.54]] (list of floats) r_3d: 3D model rotation [default = [0, 0, 0]] (list of floats) has3d: presence of 3D model [default = 1] (bool) specialtags: keywords that will be comma-delimited [default = []] (list of strs) add_description: descriptive text [default = ""] (str) lib_name: library name [default = "Potentiometers"] (str) name_additions: extra text for footprint name that will be underscore-delimited [default = []] (list of strs) script3d: script to kick off 3D model generation in FreeCad [default = ""] (str) height3d: height of 3D model [default = 10] (float) Returns: None """ padx = 1.8 * ddrill pady = padx if SMD_pads and len(SMD_padsize) >= 2: padx = SMD_padsize[0] pady = SMD_padsize[1] txt_offset = 1 slk_offset = 0.12 grid_crt = 0.01 padpos = [] padtype = Pad.TYPE_THT padstyle = Pad.SHAPE_CIRCLE if SMD_pads: padtype = Pad.TYPE_SMT padstyle = Pad.SHAPE_RECT padpos.append([1, pinxoffset, pinyoffset, ddrill, padx, pady, padtype, padstyle]) if SMD_pads and len(SMD_padsize) >= 4: padpos.append([2, pinxoffset+rmx2, pinyoffset+rmy2, ddrill, SMD_padsize[2], SMD_padsize[3], padtype, padstyle]) else: padpos.append([2, pinxoffset + rmx2, pinyoffset + rmy2, ddrill, padx, pady, padtype, padstyle]) if SMD_pads and len(SMD_padsize) >= 6: padpos.append([3, pinxoffset + rmx3, pinyoffset + rmy3, ddrill, SMD_padsize[4], SMD_padsize[5], padtype, padstyle]) else: padpos.append([3, pinxoffset+rmx3, pinyoffset+rmy3, ddrill, padx, pady, padtype, padstyle]) offset = [-pinxoffset, -pinyoffset] if SMD_pads: offset = [-(max(padpos[0][1],padpos[1][1],padpos[2][1])+min(padpos[0][1],padpos[1][1],padpos[2][1]))/2, -(max(padpos[0][2],padpos[1][2],padpos[2][2])+min(padpos[0][2],padpos[1][2],padpos[2][2]))/2] #offset = [-(pinxoffset+pinxoffset+rmx2+pinxoffset+rmx3)/3.0, -(pinyoffset+pinyoffset+rmy2+pinyoffset+rmy3)/3.0] lbody_fab = 0 tbody_fab = 0 wbody_fab = wbody hbody_fab = hbody lbody_slk = lbody_fab - slk_offset tbody_slk = tbody_fab - slk_offset wbody_slk = wbody_fab + 2 * slk_offset hbody_slk = hbody_fab + 2 * slk_offset if style == "screwtop" and shaft_hole == True: padpos.append(['', screwxoffset, screwyoffset, ddrill, ddrill, ddrill, Pad.TYPE_NPTH, Pad.SHAPE_CIRCLE]) if style=="screwleft": orientation = "horizontal" lscrew_fab=lbody_fab+screwxoffset-wscrew tscrew_fab = tbody_fab + screwyoffset-dscrew/2.0 wscrew_fab = wscrew hscrew_fab = dscrew lscrew_slk=lscrew_fab-slk_offset tscrew_slk = tscrew_fab-slk_offset wscrew_slk = wscrew_fab hscrew_slk = hscrew_fab+slk_offset*2 elif style=="screwtop": orientation = "vertical" lscrew_fab=lbody_fab+screwxoffset tscrew_fab = tbody_fab + screwyoffset wscrew_fab = dscrew hscrew_fab = dscrew lscrew_slk = lscrew_fab tscrew_slk = tscrew_fab wscrew_slk = wscrew_fab + 2*slk_offset hscrew_slk = hscrew_fab + 2*slk_offset minx = miny = 1e99 maxx = maxy = -1e99 for p in padpos: maxx = max(maxx, p[1] + p[4] / 2) minx = min(minx, p[1] - p[4] / 2) maxy = max(maxy, p[2] + p[5] / 2) miny = min(miny, p[2] - p[5] / 2) minx = min(minx, lbody_fab) miny = min(miny, tbody_fab) maxx = max(maxx, lbody_fab + wbody_fab) maxy = max(maxy, tbody_fab + hbody_fab) if style == "screwleft": minx = min(minx, lscrew_fab) miny = min(miny, tscrew_fab) maxx = max(maxx, lscrew_fab + wscrew_fab) maxy = max(maxy, tscrew_fab + hscrew_fab) h_crt = (maxy - miny) + 2 * crt_offset w_crt = (maxx - minx) + 2 * crt_offset l_crt = minx - crt_offset t_crt = miny - crt_offset pow_rat = "" if R_POW > 0: pow_rat = "{0}W".format(R_POW) if (1 / R_POW == int(1 / R_POW)): pow_rat = pow_rat + " = 1/{0}W".format(int(1 / R_POW)) tgs = specialtags tgs.append(class_name) if len(pow_rat) > 0: tgs.append(pow_rat) description = "Potentiometer, " + orientation tags = "Potentiometer " + orientation if shaft_hole: description = description + ", shaft hole" tags = tags + " hole" for t in tgs: description = description + ", " + t tags = tags + " " + t description = description + ", " + add_description for n in name_additions: footprint_name = footprint_name + "_" + n footprint_name = lib_name + "_" + "_".join(class_name.split()) + "_" + orientation.capitalize() if shaft_hole: footprint_name = footprint_name + "_Hole" print(footprint_name) if script3d != "": with open(script3d, "a") as myfile: myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("App.ActiveDocument.clearAll()\n") line = 0 line += 1; script3d_writevariable(myfile, line, 'lbody_fab', min(lbody_fab+wbody_fab,lbody_fab)+offset[0]) line += 1; script3d_writevariable(myfile, line, 'tbody_fab', min(tbody_fab+hbody_fab,tbody_fab)+offset[1]) line += 1; script3d_writevariable(myfile, line, 'wbody_fab', math.fabs(wbody_fab)) line += 1; script3d_writevariable(myfile, line, 'hbody_fab', math.fabs(hbody_fab)) line += 1; script3d_writevariable(myfile, line, 'lscrew_fab', min(lscrew_fab+wscrew_fab,lscrew_fab)+offset[0]) line += 1; script3d_writevariable(myfile, line, 'tscrew_fab', min(tscrew_fab+hscrew_fab,tscrew_fab)+offset[1]) line += 1; script3d_writevariable(myfile, line, 'wscrew_fab', math.fabs(wscrew_fab)) line += 1; script3d_writevariable(myfile, line, 'hscrew_fab', math.fabs(hscrew_fab)) line += 1; script3d_writevariable(myfile, line, 'dscrew', dscrew) line += 1; script3d_writevariable(myfile, line, 'wscrew', wscrew) line += 1; script3d_writevariable(myfile, line, 'rmxtwo', rmx2) line += 1; script3d_writevariable(myfile, line, 'rmytwo', rmy2) line += 1; script3d_writevariable(myfile, line, 'rmxthree', rmx3) line += 1; script3d_writevariable(myfile, line, 'rmythree', rmy3) for p in padpos: if p[0] == 1: line += 1; script3d_writevariable(myfile, line, 'padx', p[1]) line += 1; script3d_writevariable(myfile, line, 'pady', p[2]) line += 1; script3d_writevariable(myfile, line, 'd_wire', ddrill-0.3) line += 1; script3d_writevariable(myfile, line, 'height', height3d) line += 1; script3d_writevariable(myfile, line, 'offsetx', offset[0]) line += 1; script3d_writevariable(myfile, line, 'offsety', offset[1]) myfile.write("App.ActiveDocument.recompute()\n\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format(footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) if SMD_pads: kicad_mod.setAttribute('smd') kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[l_crt + w_crt / 2.0, t_crt - txt_offset], layer='F.SilkS')) kicad_modg.append(Text(type='value', text=footprint_name, at=[l_crt + w_crt / 2.0, t_crt + h_crt + txt_offset], layer='F.Fab')) # create FAB-layer kicad_modg.append(RectLine(start=[lbody_fab, tbody_fab], end=[lbody_fab + wbody_fab, tbody_fab + hbody_fab], layer='F.Fab', width=lw_fab)) if style == "screwleft": if wscrew > 0: kicad_modg.append(RectLine(start=[lscrew_fab, tscrew_fab], end=[lscrew_fab + wscrew_fab, tscrew_fab + hscrew_fab], layer='F.Fab',width=lw_fab)) kicad_modg.append(Line(start=[lscrew_fab, tscrew_fab+hscrew_fab/2.0], end=[lscrew_fab + wscrew_fab/2.0, tscrew_fab + hscrew_fab/2.0], layer='F.Fab', width=lw_fab)) # trimmer pot with rectangular body: place refdes on F.Fab centered in body text_size = round(min(1, lbody_fab + wbody_fab, tbody_fab + hbody_fab), 2) kicad_modg.append(Text(type='user', text='%R', at=[lbody_fab+wbody_fab/2.0, tbody_fab+hbody_fab/2.0], size=[text_size, text_size], layer='F.Fab')) elif style == "screwtop": # screw graphics are inside body somewhere, so determine where to place F.Fab ref des text if (hbody_fab / 2.0 == tscrew_fab): # screw is centered vertically in body, so place at top center of body text_x = lbody_fab + wbody_fab / 2.0 text_y = tscrew_fab - wscrew_fab + 0.3 text_size = round(min(1, (hbody_fab - wscrew_fab) / 4.0), 2) else: # determine if screw is closer to left or right side of body, then place centered on other side of body text_y = tbody_fab + hbody_fab / 2.0 if (lscrew_fab <= wbody_fab - lscrew_fab): text_x = lscrew_fab + (wbody_fab - lscrew_fab) / 2.0 text_size = round(min(1, (wbody_fab - lscrew_fab) / 6.0), 2) else: text_x = lbody_fab + lscrew_fab / 2.0 text_size = round(min(1, lscrew_fab / 6.0), 2) # trimmer pot top-mount with rectangular body: place refdes on F.Fab at location found above kicad_modg.append(Text(type='user', text='%R', at=[text_x, text_y], size=[text_size, text_size], layer='F.Fab')) if shaft_hole == False: if screwstyle=="slit": addSlitScrew(kicad_modg, lscrew_fab, tscrew_fab, wscrew_fab / 2.0, 'F.Fab', lw_fab) else: addCrossScrew(kicad_modg, lscrew_fab, tscrew_fab, wscrew_fab / 2.0, 'F.Fab', lw_fab) # build keepout for silkscreen keepouts = [] for p in padpos: if p[7] == Pad.SHAPE_CIRCLE: keepouts = keepouts + addKeepoutRound(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) else: keepouts = keepouts + addKeepoutRect(p[1], p[2], p[4] + 2 * lw_slk + 2 * slk_offset, p[5] + 2 * lw_slk + 2 * slk_offset) # debug_draw_keepouts(kicad_modg,keepouts) # create SILKSCREEN-layer addRectWithKeepout(kicad_modg, lbody_slk, tbody_slk, wbody_slk, hbody_slk, 'F.SilkS', lw_slk, keepouts) if style == "screwleft" and wscrew > 0: addRectWithKeepout(kicad_modg, lscrew_slk, tscrew_slk, wscrew_slk, hscrew_slk, 'F.SilkS', lw_slk, keepouts) addHLineWithKeepout(kicad_modg, lscrew_slk, lscrew_slk+wscrew_slk/2.0, tscrew_slk+hscrew_slk/2.0, 'F.SilkS', lw_slk, keepouts) '''elif style == "screwtop": if screwstyle == "slit": addSlitScrewWithKeepouts(kicad_modg, lscrew_slk, tscrew_slk, wscrew_slk / 2.0, 'F.SilkS', lw_slk, keepouts) else: addCrossScrewWithKeepouts(kicad_modg, lscrew_slk, tscrew_slk, wscrew_slk / 2.0, 'F.SilkS', lw_slk, keepouts)''' # create courtyard kicad_mod.append(RectLine(start=[roundG(l_crt + offset[0], grid_crt), roundG(t_crt + offset[1], grid_crt)], end=[roundG(l_crt + w_crt + offset[0], grid_crt), roundG(t_crt + h_crt + offset[1], grid_crt)], layer='F.CrtYd', width=lw_crt)) # create pads for p in padpos: if p[6] == Pad.TYPE_SMT: kicad_modg.append(Pad(number=p[0], type=p[6], shape=p[7], at=[p[1], p[2]], size=[p[4], p[5]], drill=p[3], layers=['F.Cu', 'F.Paste', 'F.Mask'])) else: kicad_modg.append(Pad(number=p[0], type=p[6], shape=p[7], at=[p[1], p[2]], size=[p[4], p[5]], drill=p[3], layers=['*.Cu', '*.Mask'])) # add model if (has3d != 0): if SMD_pads: kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + "_SMD.3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) else: kicad_modg.append(Model(filename="${KISYS3DMOD}/" + lib_name + "_THT.3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=r_3d)) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') ''' if __name__ == '__main__': # handle arguments parser = argparse.ArgumentParser() # general parameters (used for 'horizontal' types) parser.add_argument('type', help='type of potentiometer (horizontal, vertical, spindle)', nargs='?', choices=['horizontal', 'vertical', 'spindle']) parser.add_argument('--class_name', help='class_name: manufacturer and MPN like "Bourns 3214W" (str)', nargs='?', required=True) parser.add_argument('--wbody', help='wbody: body length (float)', type=float, nargs='?', required=True) parser.add_argument('--hbody', help='hbody: body height (float)', type=float, nargs='?', required=True) parser.add_argument('--wscrew', help='wscrew: collar length (float)', type=float, nargs='?') parser.add_argument('--dscrew', help='dscrew: collar diameter (float)', type=float, nargs='?', required=True) parser.add_argument('--wshaft', help='wshaft: shaft length (float)', type=float, nargs='?') parser.add_argument('--dshaft', help='dshaft: shaft diameter (float)', type=float, nargs='?') parser.add_argument('--style', help='style: type of pot from "normal" or "trimmer" [default = "normal"] (str) style: location of screw from "screwleft" or "screwtop" [default = "screwleft"] (str)', nargs='?', required=True) parser.add_argument('--pinxoffset', help='pinxoffset: distance from face of body to first column of pins [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('--pinyoffset', help='pinyoffset: distance from top of body to first row of pins [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('--pins', help='pins: number of pins; "trimmer" style can only support 3 pins [default = 3] (int)', type=int, nargs='?', default=3) parser.add_argument('--rmx', help='rmx: column spacing of pins [default = 5.08] (float)', type=float, nargs='?') parser.add_argument('--rmy', help='rmy: row (or vertical) spacing of pins [default = 5.08] (float)', type=float, nargs='?') parser.add_argument('--ddrill', help='ddrill: drill hole diameter [default = 1.5] (float)', type=float, nargs='?', required=True) parser.add_argument('--R_POW', help='R_POW: power rating of pot with zero being default [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('--x_3d', help='x_3d: 3D model location [default = [0, 0, 0]] (list of floats)', nargs=3) parser.add_argument('--s_3d', help='s_3d: 3D model scaling [default = [1 / 2.54, 1 / 2.54, 1 / 2.54]] (list of floats)', nargs=3) parser.add_argument('--r_3d', help='r_3d: 3D model rotation [default = [0, 0, 0]] (list of floats)', nargs=3) parser.add_argument('--has3d', help='has3d: presence of 3D model [default = 1] (bool)', type=bool, nargs='?', default=1) parser.add_argument('--specialtags', help='specialtags: keywords that will be comma-delimited [default = []] (list of strs)', nargs='*') parser.add_argument('--add_description', help='add_description: descriptive text [default = ""] (str)', nargs='?', default="") parser.add_argument('--lib_name', help='lib_name: library name [default = "Potentiometer"] (str)', nargs='?', default="Potentiometer") parser.add_argument('--name_additions', help='name_additions: extra text for footprint name that will be underscore-delimited [default = ""] (str)', nargs='?', default="") parser.add_argument('--script3d', help='script3d: script to kick off 3D model generation in FreeCad [default = ""] (str)', nargs='?', default="") parser.add_argument('--height3d', help='height3d: height of 3D model [default = 10] (float)', type=float, nargs='?', default=10) parser.add_argument('--screwzpos', help='screwzpos: height of collar above bottom of body [default = 5] (float)', type=float, nargs='?', default=5) parser.add_argument('--mh_count', help='mh_count: number of mounting holes; 1, 2, or 4 are supported [default = 0] (int)', type=int, nargs='?', default=0) parser.add_argument('--mh_ddrill', help='mh_ddrill: drill hole diameter of mounting holes [default = 1.5] (float)', type=float, nargs='?', default=0) parser.add_argument('--mh_rmx', help='mh_rmx: column spacing of mounting holes [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('--mh_rmy', help='mh_rmy: row spacing of mounting holes [default = 15] (float)', type=float, nargs='?', default=0) parser.add_argument('--mh_xoffset', help='mh_xoffset: distance from face of body to first column of mounting holes [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('--mh_yoffset', help='mh_yoffset: distance from top of body to first row of mounting holes [default = 0] (float)', type=float, nargs='?', default=0) # additional parameters for 'vertical' types parser.add_argument('--screwstyle', help='screwstyle: screw style from "none", "slit", or "cross" [default = "slit"] (str)', nargs='?') parser.add_argument('--d_body', help='d_body: diameter of body for circular pot [default = 0] (float)', type=float, nargs='?') parser.add_argument('--c_ddrill', help='c_ddrill: drill diameter to fit collar or zero for no hole [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('--c_offsetx', help='c_offsetx: distance from left side of body to collar center [default = 0] (float)', type=float, nargs='?') parser.add_argument('--c_offsety', help='c_offsety:: distance from top of body to collar center [default = 0] (float)', type=float, nargs='?') parser.add_argument('--shaft_hole', help='shaft_hole: places hole under pot for shaft through PCB [default = True] (bool)', type=bool, nargs='?', default=False) parser.add_argument('--SMD_pads', help='SMD_pads: allows using SMD pads [default = False] (bool)', type=bool, nargs='?', default=False) parser.add_argument('--SMD_padsize', help='SMD_padsize: X and Y dimensions of SMD pads in [X, Y] format [default = []] (list of floats)', type=float, nargs=2) parser.add_argument('--SMD_type', help='SMD_type: allow specifying the SMD pad layout from below options [default = "3-5"] (str) "3-5": 5 pin pot with 3 pins on left side and 2 pins on right side', nargs='?') parser.add_argument('--mh_smd', help='mh_smd: allows using SMD mounting holes [default = False] (bool)', type=bool, nargs='?', default=False) parser.add_argument('--mh_padsize', help='mh_padsize: X and Y dimensions of SMD mounting holes in [X, Y] format [default = []] (list of floats)', type=float, nargs=2) parser.add_argument('--mh_nopads', help='mh_nopads: allows selecting the presence of mounting holes [default = False] (bool)', type=bool, nargs='?', default=False) # additional parameters for 'spindle' types (may not use all parameters above) parser.add_argument('--rmx2', help='rmx2: distance from pin 1 left to pin 2 (float)', type=float, nargs='?') parser.add_argument('--rmy2', help='rmy2: distance from pin 1 up to pin 2 (float)', type=float, nargs='?') parser.add_argument('--rmx3', help='rmx3: distance from pin 1 left to pin 3 (float)', type=float, nargs='?') parser.add_argument('--rmy3', help='rmy3: distance from pin 1 up to pin 3 (float)', type=float, nargs='?') parser.add_argument('--screwxoffset', help='screwxoffset: distance from left side of body to screw for top screw types [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('--screwyoffset', help='screwyoffset: distance from top of body to center of screw [default = 0] (float)', type=float, nargs='?', default=0) parser.add_argument('-v', '--verbose', help='show extra information while generating the footprint', action='store_true') args = parser.parse_args() print('\n') print(args) # some special handling of arguments, especially list types '''if not args.x_3d: x_3d = [0, 0, 0] else: x_3d = args.x_3d if not args.s_3d: s_3d = [1, 1, 1] else: s_3d = args.s_3d if not args.r_3d: r_3d = [0, 0, 0] else: r_3d = args.r_3d if not args.specialtags: specialtags = [] else: specialtags = args.specialtags if not args.name_additions: name_additions = [] else: name_additions = args.name_additions''' # for troubleshooting, below are shell commands to generate a footprint in various ways: # full: all arguments are given with non-default values # miss1: one required argument checked by argparse is missing # miss2: one required argument not checked by argparse is missing # minimal: only required arguments are given #python footprint_scripts_potentiometers.py "horizontal" --class_name "Hfull" --wbody 9.3 --hbody 16.9 --wscrew 6 --dscrew 7 --wshaft 44 --dshaft 4 --style "normal" --pinxoffset 6.3 --pinyoffset 3.45 --pins 3 --rmx 5 --rmy 5 --ddrill 1.3 --R_POW 1 --x_3d 0.7 0.8 0.9 --s_3d 0.4 0.5 0.6 --r_3d 0.1 0.2 0.3 --has3d 1 --specialtags "tag1" "tag2" --add_description "http://www.omeg.co.uk/pc6bubrc.htm" --lib_name "Potentiometer" --name_additions "addition1 addition2" --script3d "pots_ver.py" --height3d 21 --screwzpos 12.5 --mh_ddrill 1.1 --mh_count 2 --mh_rmx 1 --mh_rmy 0.5 --mh_xoffset 0.2 --mh_yoffset 11 #python footprint_scripts_potentiometers.py "horizontal" --class_name "Hmiss1" --hbody 16.9 --wscrew 6 --dscrew 7 --wshaft 44 --dshaft 4 --style "normal" --pinxoffset 6.3 --pinyoffset 3.45 --pins 3 --rmx 5 --rmy 5 --ddrill 1.3 --R_POW 1 --x_3d 0.7 0.8 0.9 --s_3d 0.4 0.5 0.6 --r_3d 0.1 0.2 0.3 --has3d 1 --specialtags "tag1" "tag2" --add_description "http://www.omeg.co.uk/pc6bubrc.htm" --lib_name "Potentiometer" --name_additions "addition1 addition2" --script3d "pots_ver.py" --height3d 21 --screwzpos 12.5 --mh_ddrill 1.1 --mh_count 2 --mh_rmx 1 --mh_rmy 0.5 --mh_xoffset 0.2 --mh_yoffset 11 #python footprint_scripts_potentiometers.py "horizontal" --class_name "Hmiss2" --wbody 9.3 --hbody 16.9 --wscrew 6 --dscrew 7 --wshaft 44 --dshaft 4 --style "normal" --pinxoffset 6.3 --pinyoffset 3.45 --pins 3 --rmy 5 --ddrill 1.3 --R_POW 1 --x_3d 0.7 0.8 0.9 --s_3d 0.4 0.5 0.6 --r_3d 0.1 0.2 0.3 --has3d 1 --specialtags "tag1" "tag2" --add_description "http://www.omeg.co.uk/pc6bubrc.htm" --lib_name "Potentiometer" --name_additions "addition1 addition2" --script3d "pots_ver.py" --height3d 21 --screwzpos 12.5 --mh_ddrill 1.1 --mh_count 2 --mh_rmx 1 --mh_rmy 0.5 --mh_xoffset 0.2 --mh_yoffset 11 #python footprint_scripts_potentiometers.py "horizontal" --class_name "Hmin" --wbody 9.3 --hbody 16.9 --wscrew 6 --dscrew 7 --wshaft 44 --dshaft 4 --style "normal" --rmx 5 --rmy 5 --ddrill 1.3 #python footprint_scripts_potentiometers.py "vertical" --class_name "Vfull" --wbody 8 --hbody 16 --d_body 0 --dshaft 6 --dscrew 10 --c_ddrill 10.5 --c_offsetx 10 --c_offsety 8 --pinxoffset 0.5 --pinyoffset 3 --pins 3 --rmx 7.5 --rmy 5 --ddrill 1.3 --specialtags [] --add_description "http://www.piher-nacesa.com/pdf/20-PC16v03.pdf" --lib_name "Potentiometer" --name_additions "addition" --script3d "pots_hor_below.py" --height3d 20.5 #python footprint_scripts_potentiometers.py "vertical" --class_name "Vmiss" --hbody 16 --d_body 0 --dshaft 6 --dscrew 10 --c_ddrill 10.5 --c_offsetx 10 --c_offsety 8 --pinxoffset 0.5 --pinyoffset 3 --pins 3 --rmx 7.5 --rmy 5 --ddrill 1.3 --specialtags [] --add_description "http://www.piher-nacesa.com/pdf/20-PC16v03.pdf" --lib_name "Potentiometer" --name_additions "" --script3d "pots_hor_below.py" --height3d 20.5 #python footprint_scripts_potentiometers.py "vertical"--class_name "Vmin" --wbody 8 --hbody 16 --d_body 0 --dshaft 6 --dscrew 10 --c_ddrill 10.5 --c_offsetx 10 --c_offsety 8 --pinxoffset 0.5 --pinyoffset 3 --pins 3 --rmx 7.5 --rmy 5 --ddrill 1.3 #python footprint_scripts_potentiometers.py "spindle" --class_name "Sfull" --ddrill 1 --wbody 19.3 --hbody 4.06 --pinxoffset 16 --pinyoffset 3.3 --rmx2 -7.62 --rmy2 -2.54 --rmx3 -12.7 --rmy3 0 --dscrew 3 --wscrew 1.52 --screwxoffset 0 --screwyoffset 2.03 --style=style --screwstyle "slit" --SMD_pads True --SMD_padsize 2.5 2.5 --add_description "https://www.bourns.com/pdfs/3005.pdf" --lib_name "Potentiometer" --script3d "trimmer_screwleft.py" --height3d 7.87 # ensure all required attributes for pot type are given and, if so, pass arguments to function # note that the argparse interface traps and reports errors for the 'type' parameter and all 'horizontal' type arguments # for 'vertical' and 'spindle' types, argument presence is checked but argument type is not if (args.type == "horizontal"): if (None in [args.wscrew, args.wshaft, args.dshaft, args.rmx, args.rmy]): sys.exit("Error: All required arguments were not provided for a horizontal potentiometer") else: '''if not args.style: style = "normal" else: style = args.style''' makePotentiometerHorizontal(class_name=args.class_name, wbody=args.wbody, hbody=args.hbody, wscrew=args.wscrew, dscrew=args.dscrew, wshaft=args.wshaft, dshaft=args.dshaft, style=args.style, pinxoffset=args.pinxoffset, pinyoffset=args.pinyoffset, pins=args.pins, rmx=args.rmx, rmy=args.rmy, ddrill=args.ddrill, R_POW=args.R_POW, x_3d=args.x_3d, s_3d=args.s_3d, r_3d=args.r_3d, has3d=args.has3d, specialtags=args.specialtags, add_description=args.add_description, lib_name=args.lib_name, name_additions=args.name_additions, script3d=args.script3d, height3d=args.height3d, screwzpos=args.screwzpos, mh_ddrill=args.mh_ddrill, mh_count=args.mh_count, mh_rmx=args.mh_rmx, mh_rmy=args.mh_rmy, mh_xoffset=args.mh_xoffset, mh_yoffset=args.mh_yoffset) elif (args.type == "vertical"): if (None in [args.screwstyle, args.d_body, args.dshaft, args.c_offsetx, args.c_offsety, args.rmx, args.rmy, args.SMD_type]): sys.exit("Error: Argument(s) missing for a vertical potentiometer (screwstyle, d_body, dshaft, c_offsetx, c_offsety, rmx, rmy, SMD_type)") else: makePotentiometerVertical(class_name=args.class_name, wbody=args.wbody, hbody=args.hbody, screwstyle=args.screwstyle, style=args.style, d_body=args.d_body, dshaft=args.dshaft, dscrew=args.dscrew, c_ddrill=args.c_ddril, c_offsetx=args.c_offsetx, c_offsety=args.c_offsety, pinxoffset=args.pinxoffset, pinyoffset=args.pinyoffset, pins=args.pins, rmx=args.rmx, rmy=args.rmy, ddrill=args.ddrill, shaft_hole=args.shaft_hole, SMD_pads=args.SMD_pads, SMD_padsize=args.SMD_padsize, SMD_type=args.SMD_type, R_POW=args.R_POW, x_3d=x_3d, s_3d=s_3d, r_3d=r_3d, has3d=args.has3d, specialtags=specialtags, add_description=args.add_description, lib_name=args.lib_name, name_additions=name_additions, script3d=args.script3d, height3d=args.height3d, mh_ddrill=args.mh_drill, mh_count=args.mh_count, mh_rmx=args.mh_rmx, mh_rmy=args.mh_rmy, mh_xoffset=args.mh_xoffset, mh_yoffset=args.mh_yoffset, mh_smd=args.mh_smd, mh_padsize=args.mh_padsize, mh_nopads=args.mh_nopads) elif (args.type == "spindle"): if (None in [args.rmx2, args.rmy2, args.rmx3, args.rmy3, args.wscrew, args.screwstyle]): sys.exit("Error: Argument(s) missing for a spindle potentiometer (rmx2, rmy2, rmx3, rmy3, wscrew, screwstyle)") else: makeSpindleTrimmer(class_name=args.class_name, wbody=args.wbody, hbody=args.hbody, pinxoffset=args.pinxoffset, pinyoffset=args.pinyoffset, rmx2=args.rmx2, rmy2=args.rmy2, rmx3=args.rmx3, rmy3=args.rmy3, dscrew=args.dscrew, ddrill=args.ddrill, wscrew=args.wscrew, screwxoffset=args.screwxoffset, screwyoffset=args.screwyoffset, style=args.style, screwstyle=args.screwstyle, SMD_pads=args.SMD_pads, SMD_padsize=args.SMD_padsize, R_POW=args.R_POW, x_3d=x_3d, s_3d=s_3d, r_3d=r_3d, has3d=args.has3d, specialtags=specialtags, add_description=args.add_description, lib_name=args.lib_name, name_additions=name_additions, script3d=args.script3d, height3d=args.height3d) ''' ================================================ FILE: scripts/tools/footprint_scripts_resistorlike.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * from footprint_global_properties import * slk_offset=lw_slk # classnamefancy -> long form of class name for description field # part names uses short/ordinary classname def getFancyClassName(classname="R"): if (classname == "R"): classnamefancy = "Resistor" elif (classname == "D"): classnamefancy = "Diode" elif (classname == "L"): classnamefancy = "Inductor" else: classnamefancy = classname return classnamefancy # returns a string for the description for the power rating def getPowRat(R_POW=0.0): pow_rat = "" if not (R_POW==int(R_POW)): R_POW = round(R_POW, 3) if R_POW > 0.0: pow_rat="{0}W".format(R_POW) if (1.0/R_POW==int(1.0/R_POW)) and (R_POW<1.0): pow_rat=pow_rat+" = 1/{0}W".format(int(1.0/R_POW)) else: pow_rat="{0}W".format(R_POW) return pow_rat # simple axial round (type="cyl") / box (type="box") / bare metal wire (type="bridge") resistor, horizontally mounted # optionally with additional shunt leads: hasShuntPins=True, shuntPinsRM=DISTANCE # deco="none"/"elco"/"diode" def makeResistorAxialHorizontal(seriesname, rm, rmdisp, w, d, ddrill, R_POW, type="cyl", d2=0, hasShuntPins=False, shuntPinsRM=0, x_3d=[0,0,0], s_3d=[1, 1, 1], has3d=1, specialfpname="", specialtags=[], add_description="", classname="R", lib_name="Resistor_THT", name_additions=[], deco="none", script3d=""): padx=2*ddrill pady=padx pad1style=Pad.SHAPE_CIRCLE polsign_slk=[] if deco=="elco" or deco=="cp" or deco=="tantal" or deco=="diode": pad1style=Pad.SHAPE_RECT l_fab=(rm-w)/2 l_dbar_fab=l_fab t_fab=-d/2 h_fab=d w_fab=w h_slk=d+2*slk_offset w_slk=w+2*slk_offset l_slk=l_fab-slk_offset l_dbar_slk=l_dbar_fab r_slk=l_slk+w_slk t_slk=-h_slk/2 w_crt=rm+padx+2*crt_offset h_crt=max(d, pady)+2*crt_offset l_crt=min(l_fab, -padx/2)-crt_offset t_crt=min(-d/2, -pady/2)-crt_offset # if seriesname == "DO-34_SOD68": # print ("w{}, h{}, l{}, t{}".format(w_crt, h_crt, l_crt, t_crt)) fabtxt_size=1; fabtxt_thick=0.15 if w_fab<=5 or h_fab<=1: fabtxt_size=min(h_fab*0.8, w_fab/5) fabtxt_thick=0.15*fabtxt_size fabtxt_size=max(0.25,fabtxt_size) fabtxt_thick=max(0.15/4,fabtxt_thick) add_plus_sign_slk = False if deco=="elco" or deco=="cp" or deco=="tantal": polsign_slk=[l_slk+padx*0.75,-pady*0.75/2,padx*0.75,pady*0.75] add_plus_sign_slk = True if deco=="diode": l_dbar_fab=l_fab+w_fab*0.15 l_dbar_slk=l_dbar_fab snfp="" sn="" snt="" if len(seriesname)>0: snfp="_"+seriesname sn=", "+seriesname+" series" snt = " " + seriesname + " series" pow_rat = getPowRat(R_POW) classnamefancy = getFancyClassName(classname) fnpins="_P{0:0.2f}mm".format(rmdisp) if hasShuntPins: fnpins = "_PS{0:0.2f}mm_P{1:0.2f}mm".format(shuntPinsRM,rmdisp) dimdesc="length*diameter={0}*{1}mm^2".format(w, d) dimdesct = "length {0}mm diameter {1}mm".format(w, d) if deco=="diode": footprint_name=classname+snfp+fnpins+"_Horizontal" else: footprint_name=classname+"{3}_L{1:0.1f}mm_D{2:0.1f}mm{0}_Horizontal".format(fnpins,w,d,snfp) if type=="box": footprint_name = classname+"{4}_L{3:0.1f}mm_W{1:0.1f}mm{0}".format(fnpins, d,d2,w, snfp) dimdesc = "length*width*height={0}*{1}*{1}mm^3".format(w,d, d2) dimdesct = "length {0}mm width {1}mm height {1}mm".format(w, d, d2) description=classnamefancy+"{3}, Box, pin pitch={0}mm, {1}, {2}".format(rm, pow_rat, dimdesc,sn) tags=classnamefancy+"{3} Box pin pitch {0}mm {1} {2}".format(rm, pow_rat, dimdesct, snt) elif type=="bridge": footprint_name = classname+"{3}_L{2:0.1f}mm_W{1:0.1f}mm{0}".format(fnpins, d,w, snfp) dimdesc = "length*width={0}*{1}mm^2".format(w,d) dimdesct = "length {0}mm width {1}mm ".format(w, d) description=classnamefancy+"{3}, Bare Metal Strip/Wire, Horizontal, pin pitch={0}mm, {1}, {2}".format(rm, pow_rat, dimdesc,sn) tags=classnamefancy+"{3} Bare Metal Strip Wire Horizontal pin pitch {0}mm {1} {2}".format(rm, pow_rat, dimdesct, snt) else: description=classnamefancy+"{3}, Axial, Horizontal, pin pitch={0}mm, {1}, {2}".format(rm, pow_rat, dimdesc,sn) tags=classnamefancy+"{3} Axial Horizontal pin pitch {0}mm {1} {2}".format(rm, pow_rat, dimdesct, snt) if hasShuntPins: description = description + ", shunt pin pitch = {0:0.2f}mm".format(shuntPinsRM) tags = tags + " shunt pin pitch {0:0.2f}mm".format(shuntPinsRM) for t in specialtags: description=description+", "+t tags = tags + " " + t if (specialfpname!=""): footprint_name=specialfpname; if len(add_description) > 0: description = description + ", " + add_description for n in name_additions: if len(n)>0: footprint_name=footprint_name+"_"+n print(footprint_name) if script3d!="": with open(script3d, "a") as myfile: myfile.write("\n \"{0}\" : Params(# from Jan Kriege's 3d models\n".format(footprint_name)) myfile.write(" L = {:0.2f}, # Body Length\n".format(w)) myfile.write(" D = {:0.2f}, # Body Diameter\n".format(d)) myfile.write(" d = {:0.2f}, # Lead Diameter\n".format(ddrill-0.3)) myfile.write(" F = {:0.2f}, # Lead Seperation\n".format(rm)) myfile.write(" ll = 2.0, # Lead Length\n") myfile.write(" bs = 0.0, # Board Seperation\n") myfile.write(" modelName = '{0}', # Modelname\n".format(footprint_name)) myfile.write(" rotation = 0, # Rotation\n") myfile.write(" dest_dir_prefix = '../Capacitors_THT.3dshapes/', # Destination\n") myfile.write(" ),\n") #Jans' 3D script ''' myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '0.02')\n") myfile.write("App.ActiveDocument.recompute()\n") myfile.write("# L\nApp.ActiveDocument.Spreadsheet.set('B1', '{0}')\n".format(w) ) myfile.write("# d\nApp.ActiveDocument.Spreadsheet.set('B2', '{0}')\n".format(d)) myfile.write("# d2\nApp.ActiveDocument.Spreadsheet.set('C2', '{0}')\n".format(d2)) myfile.write("# RM\nApp.ActiveDocument.Spreadsheet.set('B3', '{0}')\n".format(rm)) myfile.write("# shuntPinsRM\nApp.ActiveDocument.Spreadsheet.set('C3', '{0}')\n".format(shuntPinsRM)) myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '{0}')\n".format(ddrill-0.3)) myfile.write("App.ActiveDocument.recompute()\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format(footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) ''' # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[rm/2, t_slk-txt_offset], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[rm/2, h_slk/2+txt_offset], layer='F.Fab')) if deco=="diode": kicad_mod.append(Text(type='user', text='%R', at=[rm/2+w_fab*0.15/2, 0], layer='F.Fab', size=[fabtxt_size, fabtxt_size], thickness=fabtxt_thick)) else: kicad_mod.append(Text(type='user', text='%R', at=[rm/2, 0], layer='F.Fab', size=[fabtxt_size, fabtxt_size], thickness=fabtxt_thick)) # create FAB-layer if deco=="elco" or deco=="cp" or deco=="tantal": kicad_mod.append(Line(start=[l_fab, t_fab], end=[l_fab, t_fab+d], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[l_fab+w, t_fab], end=[l_fab+w, t_fab+d], layer='F.Fab', width=lw_fab)) kicad_mod.append(PolygoneLine(polygone=[[l_fab, t_fab], [polsign_slk[0], t_fab], [polsign_slk[0]+polsign_slk[2]/2, t_fab+polsign_slk[3]/2], [polsign_slk[0]+polsign_slk[2], t_fab],[l_fab+w, t_fab]], layer='F.Fab', width=lw_fab)) kicad_mod.append(PolygoneLine(polygone=[[l_fab, t_fab+d], [polsign_slk[0], t_fab+h_fab], [polsign_slk[0]+polsign_slk[2]/2, t_fab+h_fab-polsign_slk[3]/2], [polsign_slk[0]+polsign_slk[2], t_fab+h_fab],[l_fab+w, t_fab+d]], layer='F.Fab', width=lw_fab)) else: kicad_mod.append(RectLine(start=[l_fab, t_fab], end=[l_fab+w, t_fab+d], layer='F.Fab', width=lw_fab)) if type != "bridge": kicad_mod.append(Line(start=[0, 0], end=[l_fab, 0], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[rm, 0], end=[l_fab+w, 0], layer='F.Fab', width=lw_fab)) if len(polsign_slk)==4: addPlusWithKeepout(kicad_mod, polsign_slk[0],polsign_slk[1], polsign_slk[2],polsign_slk[3], 'F.Fab', lw_fab, [], 0.05) if deco=="diode": kicad_mod.append(Line(start=[l_dbar_fab, t_fab], end=[l_dbar_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[l_dbar_fab+lw_fab, t_fab], end=[l_dbar_fab+lw_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[l_dbar_fab-lw_fab, t_fab], end=[l_dbar_fab-lw_fab, t_fab+h_fab], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer if add_plus_sign_slk: polsign_size = padx*0.75 # (((d_fab-polsign_size)/2.0-polsign_size/10.0) polsign_pos_x = l_slk-padx/2. polsign_pos_y = -pady-min_pad_distance kicad_mod.append(Line(start=[polsign_pos_x-polsign_size/2., polsign_pos_y], end=[polsign_pos_x+polsign_size/2.,polsign_pos_y], layer='F.SilkS', width=lw_slk)) kicad_mod.append(Line(start=[polsign_pos_x, polsign_pos_y-polsign_size/2.], end=[polsign_pos_x,polsign_pos_y+polsign_size/2.], layer='F.SilkS', width=lw_slk)) if deco=="elco" or deco=="cp" or deco=="tantal": kicad_mod.append(Line(start=[l_slk, t_slk], end=[l_slk, t_slk+h_slk], layer='F.SilkS', width=lw_slk)) kicad_mod.append(Line(start=[l_slk+w_slk, t_slk], end=[l_slk+w_slk, t_slk+h_slk], layer='F.SilkS', width=lw_slk)) kicad_mod.append(PolygoneLine(polygone=[[l_slk, t_slk], [polsign_slk[0], t_slk], [polsign_slk[0]+polsign_slk[2]/2, t_slk+polsign_slk[3]/2], [polsign_slk[0]+polsign_slk[2], t_slk],[l_slk+w_slk, t_slk]], layer='F.SilkS', width=lw_slk)) kicad_mod.append(PolygoneLine(polygone=[[l_slk, t_slk+h_slk], [polsign_slk[0], t_slk+h_slk], [polsign_slk[0]+polsign_slk[2]/2, t_slk+h_slk-polsign_slk[3]/2], [polsign_slk[0]+polsign_slk[2], t_slk+h_slk],[l_slk+w_slk, t_slk+h_slk]], layer='F.SilkS', width=lw_slk)) else: if l_slkrm-0.3: padx=max(ddrill+0.3, rm-0.3) pady = padx if (largepadsx): padx = max(padx, largepadsx) if (largepadsy): pady = max(pady, largepadsy) pad1style=Pad.SHAPE_CIRCLE polsign_slk=[] if deco=="elco" or deco=="cp" or deco=="tantal" or deco=="diode" or deco=="diode_KUP": pad1style=Pad.SHAPE_RECT l_fab = -d / 2 if deco=="diode_KUP": l_fab=-padx/2 t_fab = -d / 2 d_slk = max(max(padx, pady) + 0.15, d + 2 * slk_offset) if pad1style==Pad.SHAPE_RECT: d_slk = max(max(padx, pady)*math.sqrt(2) + 0.15, d )+ 2 * slk_offset d2_slk = max(max(padx, pady) + 0.15, d2 + 2 * slk_offset) w_slk = rm + d / 2 + padx / 2 + 2 * slk_offset l_slk = l_fab - slk_offset r_slk = l_slk + w_slk t_slk = -d_slk / 2 w_crt = rm + d / 2 + padx / 2 + 2 * crt_offset h_crt = max(pady, d) + 2 * crt_offset l_crt = l_fab - crt_offset t_crt = t_fab - crt_offset fabtxt_size=1; fabtxt_thick=0.15 if d<=5: fabtxt_size=d/5 fabtxt_thick=0.15*fabtxt_size fabtxt_size=max(0.25,fabtxt_size) fabtxt_thick=max(0.15/4,fabtxt_thick) valoffset=0 if deco=="diode" or deco=="diode_KUP": d_size=min(0.35*rm, padx) d_y=0 d_x=rm/2 if d_size>rm-padx-slk_offset*2-lw_slk*2: d_y=pady/2+slk_offset+lw_slk+d_size/2 valoffset=d_size d_x=rm*2/3 if d_size+padx/2+2*slk_offset 0: snfp = "_" + seriesname sn = ", " + seriesname + " series" snt = " " + seriesname + " series" pow_rat = getPowRat(R_POW) dimdesc = "length*diameter={0}*{1}mm^2".format(l, d) dimdesct = "length {0}mm diameter {1}mm".format(l, d) classnamefancy = getFancyClassName(classname) if deco=="diode": footprint_name = classname+"{1}_P{0:0.2f}mm_Vertical_AnodeUp".format(rmdisp, snfp) elif deco=="diode_KUP": footprint_name = classname+"{1}_P{0:0.2f}mm_Vertical_KathodeUp".format(rmdisp, snfp) else: footprint_name = classname+"{3}_L{1:0.1f}mm_D{2:0.1f}mm_P{0:0.2f}mm_Vertical".format(rmdisp, l, d, snfp) if type == "box": footprint_name = classname+"{4}_L{3:0.1f}mm_W{1:0.1f}mm_P{0:0.2f}mm_Vertical".format(rmdisp, d, d2, l, snfp) dimdesc = "length*width*height={0}*{1}*{1}mm^3".format(l, d, d2) dimdesct = "length {0}mm width {1}mm height {1}mm".format(l, d, d2) description = classnamefancy+"{3}, Axial, Vertical, pin pitch={0}mm, {1}, {2}".format(rm, pow_rat, dimdesc, sn) tags = classnamefancy+"{3} Axial Vertical pin pitch {0}mm {1} {2}".format(rm, pow_rat, dimdesct, snt) for t in specialtags: description = description + ", " + t tags = tags + " " + t if (specialfpname != ""): footprint_name = specialfpname; if len(add_description) > 0: description = description + ", " + add_description for n in name_additions: if len(n)>0: footprint_name=footprint_name+"_"+n print(footprint_name) if script3d!="": with open(script3d, "a") as myfile: myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '0.02')\n") myfile.write("App.ActiveDocument.recompute()\n") myfile.write("# L\nApp.ActiveDocument.Spreadsheet.set('B1', '{0}')\n".format(l) ) myfile.write("# d\nApp.ActiveDocument.Spreadsheet.set('B2', '{0}')\n".format(d)) myfile.write("# d2\nApp.ActiveDocument.Spreadsheet.set('C2', '{0}')\n".format(d2)) myfile.write("# RM\nApp.ActiveDocument.Spreadsheet.set('B3', '{0}')\n".format(rm)) myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '{0}')\n".format(ddrill-0.3)) myfile.write("App.ActiveDocument.recompute()\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format(footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[rm / 2, t_slk - txt_offset], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[rm / 2, d_slk / 2 + txt_offset+valoffset], layer='F.Fab')) if deco=="diode_KUP": if d/2-pady/2>1.5*fabtxt_size: kicad_mod.append(Text(type='user', text='%R', at=[rm, -pady/2-fabtxt_size/2], layer='F.Fab', size=[fabtxt_size, fabtxt_size], thickness=fabtxt_thick)) else: kicad_mod.append(Text(type='user', text='%R', at=[rm / 2, t_slk - txt_offset], layer='F.Fab')) else: # diode, resistor, etc. if d/2-pady/2>1.5*fabtxt_size: kicad_mod.append(Text(type='user', text='%R', at=[0, -pady/2-fabtxt_size/2], layer='F.Fab', size=[fabtxt_size, fabtxt_size], thickness=fabtxt_thick)) else: kicad_mod.append(Text(type='user', text='%R', at=[rm / 2, t_slk - txt_offset], layer='F.Fab')) # create FAB-layer if type=="cyl": if deco=="diode_KUP": kicad_mod.append(Circle(center=[rm, 0], radius=d / 2, layer='F.Fab', width=lw_fab)) else: kicad_mod.append(Circle(center=[0, 0], radius=d / 2, layer='F.Fab', width=lw_fab)) else: kicad_mod.append(RectLine(start=[-d/2, -d2/2], end=[d/2,d2/2], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[0, 0], end=[rm,0], layer='F.Fab', width=lw_fab)) if deco=="diode": if rm>d/2*1.2 and d/2-pady/2<1: if rm<3: kicad_mod.append(Text(type='user', text="A", at=[rm+padx/2+1,0], layer='F.Fab')) kicad_mod.append(Text(type='user', text="A", at=[rm+padx/2+1,0], layer='F.SilkS')) else: kicad_mod.append(Text(type='user', text="A", at=[rm-padx/2-0.7,(pady/2)], layer='F.Fab')) kicad_mod.append(Text(type='user', text="A", at=[rm-padx/2-0.7,(pady/2)], layer='F.SilkS')) else: kicad_mod.append(Text(type='user', text="A", at=[rm,(pady/2+1)], layer='F.Fab')) kicad_mod.append(Text(type='user', text="A", at=[rm,(pady/2+1)], layer='F.SilkS')) elif deco=="diode_KUP": if rm>d/2*1.2 and d/2-pady/2<1: if rm<3: kicad_mod.append(Text(type='user', text="K", at=[0-padx/2-1,0], layer='F.Fab')) kicad_mod.append(Text(type='user', text="K", at=[0-padx/2-1,0], layer='F.SilkS')) else: kicad_mod.append(Text(type='user', text="K", at=[0+padx/2+0.7,(pady/2)], layer='F.Fab')) kicad_mod.append(Text(type='user', text="K", at=[0+padx/2+0.7,(pady/2)], layer='F.SilkS')) else: kicad_mod.append(Text(type='user', text="K", at=[0,(pady/2+1)], layer='F.Fab')) kicad_mod.append(Text(type='user', text="K", at=[0,(pady/2+1)], layer='F.SilkS')) # create SILKSCREEN-layer xs1 = d_slk / 2 xs2 = rm - padx / 2 - 0.3 if (xs1 < xs2): if type == "cyl": if deco=="diode_KUP": xs1 = rm-d_slk / 2 xs2 = padx / 2 + 0.3 kicad_mod.append(Circle(center=[rm, 0], radius=d_slk / 2, layer='F.SilkS', width=lw_slk)) else: kicad_mod.append(Circle(center=[0, 0], radius=d_slk / 2, layer='F.SilkS', width=lw_slk)) else: kicad_mod.append(RectLine(start=[-d_slk/2, -d2_slk/2], end=[d_slk/2,d2_slk/2], layer='F.SilkS', width=lw_slk)) kicad_mod.append(Line(start=[xs1, 0], end=[xs2, 0], layer='F.SilkS', width=lw_slk)) else: yy = (pady+slk_offset+lw_slk)/2 #I don't know why rectangle pads would allow silk nearer to the pad. -> removed for this reason # if pad1style==Pad.SHAPE_RECT: # yy=(pady+slk_offset)/2 xx=math.sqrt((d_slk/2)**2-(yy)**2) alpha=360-2*math.degrees(math.acos(xx/(d_slk/2))) if type == "cyl": if deco=="diode_KUP": kicad_mod.append(Arc(center=[rm, 0], start=[rm-xx, -yy], angle=alpha, layer='F.SilkS', width=lw_slk)) else: kicad_mod.append(Arc(center=[0, 0], start=[xx, -yy], angle=-alpha, layer='F.SilkS', width=lw_slk)) else: kicad_mod.append(PolygoneLine(polygone=[[d_slk/2, -yy], [d_slk / 2, -d2_slk / 2], [-d_slk / 2, -d2_slk / 2], [d_slk / 2, -d2_slk / 2], [d_slk / 2, +yy]], layer='F.SilkS', width=lw_slk)) # if deco=="diode" or deco=="diode_KUP": # kicad_mod.append(Line(start=[d_x-d_size/3, d_y-0.5*d_size], end=[d_x-d_size/3, d_y+0.5*d_size], layer='F.SilkS', width=lw_slk)) # kicad_mod.append(PolygoneLine(polygone=[[d_x-d_size/3, d_y], # [d_x+d_size/3, d_y-0.5*d_size], # [d_x+d_size/3, d_y+0.5*d_size], # [d_x-d_size/3, d_y]], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=pad1style, at=[0, 0], size=[padx, pady], drill=ddrill, layers=['*.Cu', '*.Mask'])) kicad_mod.append(Pad(number=2, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[rm, 0], size=[padx, pady], drill=ddrill, layers=['*.Cu', '*.Mask'])) # add model if (has3d != 0): kicad_mod.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=x_3d, scale=s_3d, rotate=[0, 0, 0])) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') # simple radial rectangular resistor, vertically mounted # style options: # 1. type="simple" # +----------------+ ^ # | | | # | OO OO | h # | | | # +----------------+ v # <---rm---> # <-------w--------> # 2. type="simple", vlines=True # +-+------------+-+ ^ # | | | | | # | | OO OO | | h # | | | | | # +-+------------+-+ v # <--rm--> # <-------w--------> # <----w2------> # 3. type="simple45" # +----------------+ ^ # | OO | | ^rm2 # | OO | h v # | | | # +----------------+ v # <-rm-> # <-------w--------> # 4. type="simple45", vlines=True # +-+------------+-+ ^ # | | OO | | | ^rm2 # | | OO | | h v # | | | | | # +-+------------+-+ v # <-rm-> # <-------w--------> # <----w2------> # 5. type="round": ellipse, diameter w/h # 6. type="disc" # +----------------+ ^ # | | | # | OO OO | h # | | | # +----------------+ v # <---rm---> # <-------w--------> # 7. type="disc45" # +----------------+ ^ # | OO | | ^ # | | h rm2 # | OO | | v # +----------------+ v # <-rm-> # <-------w--------> # 8. type="simplesymm45" # +----------------+ ^ # | OO | | ^ # | | h rm2 # | OO | | v # +----------------+ v # <---rm---> # <-------w--------> # 9. type="concentric": ellipse, diameter w + ellipse, diameter w2 h # 10. type="simple90" # +----------------+ ^ # | OO | | ^ # | | h rm # | OO | | v # +----------------+ v # <-------w--------> # # # deco="none","elco" (round),"tantal" (simple),"chokewire" (concentric) def makeResistorRadial(seriesname, rm, w, h, ddrill, R_POW, innerw=0,innerh=0,rm2=0, pins=2, vlines=False,w2=0, type="simple", x_3d=[0, 0, 0], s_3d=[1,1,1], has3d=1, specialfpname="", specialtags=[], add_description="", classname="R", lib_name="Resistor_THT", name_additions=[], deco="none",script3d="",height3d=10, additionalPins=[]): if innerw<=0: innerw=w if innerh<=0: innerh=h padx = 2 * ddrill pady = padx txtoffset=txt_offset add_pol_sign = False pad1style=Pad.SHAPE_CIRCLE if deco=="elco" or deco=="cp" or deco=="tantal": pad1style=Pad.SHAPE_RECT padpos=[] offset=[0,0] if type=="simple" or type=="disc" or type=="round" or type=="concentric": if pins == 4 and rm2 > 0: padpos.append([1, -rm2 / 2, -rm / 2, ddrill, padx, pady]) padpos.append([4, rm2 / 2, -rm / 2, ddrill, padx, pady]) padpos.append([3, rm2 / 2, rm / 2, ddrill, padx, pady]) padpos.append([2, -rm2 / 2, rm / 2, ddrill, padx, pady]) offset = [rm2 / 2, rm / 2] pad1style = Pad.SHAPE_RECT else: padpos.append([1,- rm / 2, 0, ddrill,padx,pady]) padpos.append([2,rm / 2, 0, ddrill,padx,pady]) offset=[rm/2,0] elif type == "simple45": padpos.append([1,0, 0, ddrill,padx,pady]) padpos.append([2,rm,-rm2, ddrill,padx,pady]) offset = [0, 0] elif type == "simplesymm45": padpos.append([1,-rm/2, rm2/2, ddrill,padx,pady]) padpos.append([2, rm/2, -rm2/2, ddrill,padx,pady]) offset = [rm/2, -rm2/2] elif type == "simple90": if pins==4 and rm2>0: padpos.append([1, -rm2/2, rm/2, ddrill,padx,pady]) padpos.append([4, rm2/2, rm/2, ddrill,padx,pady]) padpos.append([3, rm2/2, -rm/2, ddrill,padx,pady]) padpos.append([2, -rm2/2, -rm/2, ddrill,padx,pady]) offset = [rm2/2, -rm/2] pad1style=Pad.SHAPE_RECT else: padpos.append([1, 0, -rm/2, ddrill,padx,pady]) padpos.append([2, 0, rm/2, ddrill,padx,pady]) offset = [0, rm/2] #txtoffset=max(txt_offset,pady*2/3) elif type == "disc45": padpos.append([1,-rm/2, -rm2/2, ddrill,padx,pady]) padpos.append([2,rm/2,rm2/2, ddrill,padx,pady]) offset = [rm/2, rm2/2] if deco=="elco" or deco=="cp" or deco=="tantal": x=0 y=0 for p in padpos: if p[0]==1: x=min(x, p[1]) y=min(y, p[2]) #print(x,y) add_pol_sign = True rmm2=0 secondPitch=False if rm2>rm and ( type=="concentric" or type=="round"): secondPitch=True rmm2=0 yy=pady xx=math.sqrt(rm2*rm2/4-yy*yy) padpos.append([1,-xx, -yy, ddrill,padx,pady]) padpos.append([2,xx,yy, ddrill,padx,pady]) if rm2>rm and type=="simple" and pins == 2: secondPitch=True rmm2=0 padpos.append([1,-rm2/2, 0, ddrill,padx,pady]) padpos.append([2,rm2/2,0, ddrill,padx,pady]) offset=[max(rm2/2,rm/2),0] elif rm2>rm and type=="simple" and pins == 4: rmm2=0 elif type=="simple90": rmm2=rm for ep in additionalPins: padpos.append([ep[0],ep[1]-offset[0], ep[2]-offset[1], ep[3],ep[3]*2,ep[3]*2]) #print(polsign_slk) l_fab = -w / 2 t_fab = -h / 2 il_fab = -innerw / 2 it_fab = -innerh / 2 lvl1_fab = -w2 / 2 lvl2_fab = w2 / 2 w_fab = w h_fab = h iw_fab = innerw ih_fab = innerh d_fab = max(w, h) r_fab = d_fab/2. d2_fab=w2 h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset lvl1_slk=lvl1_fab lvl2_slk = lvl2_fab d_slk=d_fab+lw_slk+slk_offset r_slk = d_slk/2. d2_slk=d2_fab-lw_slk-slk_offset w_crt = max(w_fab, rm+padx) + 2 * crt_offset h_crt = max(h_fab, rmm2+pady) + 2 * crt_offset l_crt = -w_crt/2 t_crt = -h_crt/2 fabtxt_size=1; fabtxt_thick=0.15 if w_fab<=5 or h_fab<=1: fabtxt_size=min(h_fab*0.8, w_fab/5) fabtxt_thick=0.15*fabtxt_size fabtxt_size=max(0.25,fabtxt_size) fabtxt_thick=max(0.15/4,fabtxt_thick) snfp = "" sn = "" snt = "" if len(seriesname) > 0: snfp = "_" + seriesname sn = ", " + seriesname + " series" snt = " " + seriesname + " series" pow_rat = getPowRat(R_POW) fnpins = "_P{0:0.2f}mm".format(rm) pind="{0:0.2f}mm".format(rm) if secondPitch: fnpins = fnpins+"_P{0:0.2f}mm".format(rm2) pind=pind+" {0:0.2f}mm".format(rm2) if type == "simple45" or type=="disc45" or type=="simplesymm45" or pins==4: fnpins = "_Px{0:0.2f}mm_Py{1:0.2f}mm".format(rm,rm2) pind = "{0:0.2f}*{1:0.2f}mm^2".format(rm,rm2) dimdesc = "length*width={0}*{1}mm^2".format(w, h) dimdesct = "length {0}mm width {1}mm".format(w, h) if type == "disc" or type == "disc45": dimdesc = "diameter*width={0}*{1}mm^2".format(w, h) dimdesct = "diameter {0}mm width {1}mm".format(w, h) classnamefancy = getFancyClassName(classname) if type=="round" or type == "concentric": if w==h: dimdesc = "diameter={0}mm, height={1}mm".format(w, height3d) dimdesct = "diameter {0}mm height {1}mm".format(w, height3d) else: dimdesc = "diameterX*diameterY={0}*{1}mm^2".format(w, h) dimdesct = "diameterX {0}mm diameterY {1}mm".format(w, h) if classname[0].upper() == "C": footprint_name = classname + "{2}_D{1:0.1f}mm_H{3:0.1f}mm{0}".format(fnpins, w, snfp, height3d) # radial caps else: footprint_name = classname + "{2}_D{1:0.1f}mm{0}".format(fnpins, w, snfp) elif type=="disc" or type == "disc45": footprint_name = classname+"{3}_D{1:0.1f}mm_W{2:0.1f}mm{0}".format(fnpins, w, h, snfp) else: if classname[0].upper() == "C": footprint_name = classname+"{3}_L{1:0.1f}mm_W{2:0.1f}mm_H{4:0.1f}mm{0}".format(fnpins, w, h, snfp, height3d) #rect (box) caps else: footprint_name = classname+"{3}_L{1:0.1f}mm_W{2:0.1f}mm{0}".format(fnpins, w, h, snfp) if classname[0].upper() == "C": description = classnamefancy+"{2}, Radial, pin pitch={0}, {1}".format(pind, dimdesc, sn) tags = classnamefancy+"{2} Radial pin pitch {0} {1}".format(pind, dimdesct, snt) else: description = classnamefancy+"{3}, Radial, pin pitch={0}, {1}, {2}".format(pind, pow_rat, dimdesc, sn) tags = classnamefancy+"{3} Radial pin pitch {0} {1} {2}".format(pind, pow_rat, dimdesct, snt) for t in specialtags: description = description + ", " + t tags = tags + " " + t if (specialfpname != ""): footprint_name = specialfpname if len(add_description) > 0: description = description + ", " + add_description for n in name_additions: if len(n)>0: footprint_name=footprint_name+"_"+n print(footprint_name) if script3d!="": with open(script3d, "a") as myfile: myfile.write("\n \"{0}\" : Params(# from Jan Kriege's 3d models\n".format(footprint_name)) if seriesname != "Disc" and seriesname != "Radial_Tantal": myfile.write(" H = {:0.2f}, # Body Height\n".format(height3d)) myfile.write(" L = {:0.2f}, # Body Length\n".format(innerw)) myfile.write(" W = {:0.2f}, # Body Width\n".format(innerh)) myfile.write(" d = {:0.2f}, # Lead Diameter\n".format(ddrill-0.3)) if secondPitch: myfile.write(" F = {:0.2f}, # Lead Seperation\n".format(rm2)) else: myfile.write(" F = {:0.2f}, # Lead Seperation\n".format(rm)) myfile.write(" ll = 2.0, # Lead Length\n") myfile.write(" bs = 0.1, # Board Seperation\n") if seriesname == "Rect": if len(name_additions) > 0 and name_additions[0] == "MKT": myfile.write(" series = 'MKT', # 'MKS' or 'MKT'\n") else: myfile.write(" series = 'MKS', # 'MKS' or 'MKT'\n") myfile.write(" modelName = '{0}', # Modelname\n".format(footprint_name)) myfile.write(" rotation = 0, # Rotation\n") myfile.write(" dest_dir_prefix = '../Capacitors_THT.3dshapes/', # Destination\n") myfile.write(" ),\n") # Jan's Script ''' myfile.write("\n\n # {0}\n".format(footprint_name)) myfile.write("import FreeCAD\n") myfile.write("import os\n") myfile.write("import os.path\n\n") myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '0.02')\n") myfile.write("App.ActiveDocument.recompute()\n") myfile.write("# Wx\nApp.ActiveDocument.Spreadsheet.set('B1', '{0}')\n".format(innerw) ) myfile.write("# iWx\nApp.ActiveDocument.Spreadsheet.set('D1', '{0}')\n".format(w) ) myfile.write("# W2\nApp.ActiveDocument.Spreadsheet.set('C1', '{0}')\n".format(w2) ) myfile.write("# Wy\nApp.ActiveDocument.Spreadsheet.set('B2', '{0}')\n".format(innerh) ) myfile.write("# iWy\nApp.ActiveDocument.Spreadsheet.set('D2', '{0}')\n".format(h) ) myfile.write("# RMx\nApp.ActiveDocument.Spreadsheet.set('B3', '{0}')\n".format(rm) ) myfile.write("# RMy\nApp.ActiveDocument.Spreadsheet.set('C3', '{0}')\n".format(rm2) ) myfile.write("# H\nApp.ActiveDocument.Spreadsheet.set('B5', '{0}')\n".format(height3d) ) myfile.write("# offsetx\nApp.ActiveDocument.Spreadsheet.set('B6', '{0}')\n".format(-(l_fab+offset[0])) ) myfile.write("# d_wire\nApp.ActiveDocument.Spreadsheet.set('B4', '{0}')\n".format(ddrill-0.3)) if len(additionalPins)>0: ep=additionalPins[0] myfile.write("# d_wire_pin3\nApp.ActiveDocument.Spreadsheet.set('C4', '{0}')\n".format(ep[3]-0.3)) myfile.write("# pin3x\nApp.ActiveDocument.Spreadsheet.set('B5', '{0}')\n".format(ep[1])) myfile.write("# pin3x\nApp.ActiveDocument.Spreadsheet.set('C5', '{0}')\n".format(ep[2])) myfile.write("App.ActiveDocument.recompute()\n") myfile.write("doc = FreeCAD.activeDocument()\n") myfile.write("__objs__=[]\n") myfile.write("for obj in doc.Objects: \n") myfile.write(" if obj.ViewObject.Visibility:\n") myfile.write(" __objs__.append(obj)\n") myfile.write("\nFreeCADGui.export(__objs__,os.path.split(doc.FileName)[0]+os.sep+\"{0}.wrl\")\n".format(footprint_name)) myfile.write("doc.saveCopy(os.path.split(doc.FileName)[0]+os.sep+\"{0}.FCStd\")\n".format(footprint_name)) myfile.write("print(\"created {0}\")\n".format(footprint_name)) ''' # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[0, t_crt - txtoffset], layer='F.SilkS')) kicad_modg.append(Text(type='value', text=footprint_name, at=[0, t_crt+h_crt + txtoffset], layer='F.Fab')) kicad_mod.append(Text(type='user', text='%R', at=[rm/2, 0], layer='F.Fab', size=[fabtxt_size, fabtxt_size], thickness=fabtxt_thick)) # create FAB-layer if type=="round" or type=="concentric": kicad_modg.append(Circle(center=[l_fab+w_fab/2, t_fab+h_fab/2], radius=d_fab/2, layer='F.Fab', width=lw_fab)) if w2>0 and type=="concentric": kicad_modg.append(Circle(center=[l_fab+w_fab/2, t_fab+h_fab/2], radius=d2_fab/2, layer='F.Fab', width=lw_fab)) if deco=="chokewire": alpha1=0 alpha2=15 while alpha1<=360: kicad_modg.append(Line(start=[d_slk*0.49*math.cos(alpha1/180*3.1415),d_slk*0.49*math.sin(alpha1/180*3.1415)], end=[d2_slk*0.51*math.cos(alpha2/180*3.1415),d2_slk*0.51*math.sin(alpha2/180*3.1415)], layer='F.Fab', width=lw_fab)) alpha1=alpha1+30 alpha2=alpha2+30 else: kicad_modg.append(RectLine(start=[l_fab, t_fab], end=[l_fab + w_fab, t_fab + h_fab], layer='F.Fab', width=lw_fab)) if innerw!=w or innerh!=h: kicad_modg.append(RectLine(start=[il_fab, it_fab], end=[il_fab + iw_fab, it_fab + ih_fab], layer='F.Fab', width=lw_fab)) if vlines: kicad_modg.append(Line(start=[lvl1_fab, t_fab], end=[lvl1_fab,t_fab+h_fab], layer='F.Fab', width=lw_fab)) kicad_modg.append(Line(start=[lvl2_fab, t_fab], end=[lvl2_fab, t_fab + h_fab], layer='F.Fab', width=lw_fab)) if deco=="chokewire": ww=w_fab tt=t_fab hh=h_fab ll=l_fab if innerw != w or innerh != h: ww=iw_fab tt=it_fab hh=ih_fab ll=il_fab x1=ll x2=ll+0.05*ww while x2 0: pad_pos_x_max= 0 pad_pos_y_max= 0 for p in padpos: pad_pos_x_max=max(pad_pos_x_max, abs(p[1])) pad_pos_y_max=max(pad_pos_y_max, abs(p[2])) sq_pad_x_max = pad_pos_x_max+padx/2.+min_pad_distance+lw_slk/2. sq_pad_y_min = pad_pos_y_max+pady/2.+min_pad_distance+lw_slk/2 #check if silkscreen will hit the pad or pad clearance slk_x_test = math.sqrt((r_slk*r_slk)-(sq_pad_y_min * sq_pad_y_min)) if sq_pad_x_max > slk_x_test: #test circular pad clearance round_pad_x_max = sq_pad_x_max if round_pad_x_max < r_slk: if rm2 == 0: start_angle = math.degrees(math.asin(sq_pad_y_min/r_slk)) arc_angle = 360-(start_angle*2.) else: arc_angle = 340 kicad_modg.append(Arc(center=[0,0], start=[-slk_x_test, -sq_pad_y_min], angle=arc_angle, layer='F.SilkS', width=lw_slk)) else: start_angle = math.degrees(math.asin(sq_pad_y_min/r_slk)) arc_angle = 180-(start_angle*2.) kicad_modg.append(Arc(center=[0,0], start=[-slk_x_test, -sq_pad_y_min], angle=arc_angle, layer='F.SilkS', width=lw_slk)) kicad_modg.append(Arc(center=[0,0], start=[-slk_x_test, sq_pad_y_min], angle=-arc_angle, layer='F.SilkS', width=lw_slk)) else: kicad_modg.append(Circle(center=[l_slk + w_slk / 2, t_slk + h_slk / 2], radius=d_slk/2, layer='F.SilkS', width=lw_slk)) if deco=="elco": x=0; while xt_fab+h_fab): t_crt = t_fab - crt_offset h_crt=h_fab+(pady/2-math.fabs(t_fab))+2*crt_offset print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # create pads keepout=[] if not 1 in missing_pins: kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=pad, drill=ddrill, layers=['*.Cu', '*.Mask'])) keepout=keepout+addKeepoutRect(0,0,pad[0]+2*min_pad_distance+2*lw_slk, pad[1]+2*min_pad_distance+2*lw_slk) for x in range(2, pins + 1): if not x in missing_pins: kicad_mod.append(Pad(number=x, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[(x - 1) * rm, 0], size=pad, drill=ddrill, layers=['*.Cu', '*.Mask'])) if (padx/pady)<1.05 and (padx/pady)>.95: keepout=keepout+addKeepoutRect((x - 1) * rm,0,pad[0]+2*min_pad_distance+2*lw_slk, pad[1]+2*min_pad_distance+2*lw_slk) else: keepout=keepout+addKeepoutRound((x - 1) * rm,0,pad[0]+2*min_pad_distance+2*lw_slk, pad[1]+2*min_pad_distance+2*lw_slk) # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[(pins-1) / 2 * rm, min(-pady/2,t_slk) - txt_offset], layer='F.SilkS')) kicad_mod.append(Text(type='user', text='%R', at=[(pins-1) / 2 * rm, t_fab +h_fab/2], layer='F.Fab')) kicad_mod.append(Text(type='value', text=footprint_name, at=[(pins-1) / 2 * rm, t_fab+h_fab + txt_offset], layer='F.Fab')) # create FAB-layer pin1TL=True pin1size=min(1, h_fab/2) if top_offset>h_fab/2: bevelRectBL(kicad_mod, x=[l_fab, t_fab], size=[w_fab, h_fab], bevel_size=pin1size, layer='F.Fab', width=lw_fab) pin1TL=False else: bevelRectTL(kicad_mod, x=[l_fab, t_fab], size=[w_fab, h_fab], bevel_size=pin1size, layer='F.Fab', width=lw_fab) pin1TL=True # create SILKSCREEN-layer addRectWithKeepout(kicad_mod, l_slk, t_slk, w_slk, h_slk, keepouts=keepout, layer='F.SilkS', width=lw_slk) if pin1TL: addPolyLineWithKeepout(kicad_mod, [ [l_slk-2*lw_slk, t_slk+pin1size], [l_slk-2*lw_slk, t_slk-2*lw_slk], [l_slk+pin1size, t_slk-2*lw_slk], ], keepouts=keepout, layer='F.SilkS', width=lw_slk) else: addPolyLineWithKeepout(kicad_mod, [ [l_slk-2*lw_slk, t_slk+h_slk-pin1size], [l_slk-2*lw_slk, t_slk+h_slk+2*lw_slk], [l_slk+pin1size, t_slk+h_slk+2*lw_slk], ], keepouts=keepout, layer='F.SilkS', width=lw_slk) # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt)], layer='F.CrtYd', width=lw_crt)) # add model kicad_mod.append(Model(filename="${KISYS3DMOD}/"+lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0, 0, 0], scale=[1,1,1], rotate=[0, 0, 0])) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') def makeSIPHorizontal(pins, rm, ddrill, pad, package_size, left_offset, pin_bottom_offset, footprint_name, description, tags, lib_name, missing_pins=[]): padx=pad[0] pady=pad[1] w_fab=package_size[0] h_fab=package_size[2] l_fab=-left_offset t_fab=-pin_bottom_offset-h_fab h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab-slk_offset w_crt = w_fab + 2 * crt_offset h_crt = h_fab+pin_bottom_offset+pad[1]/2 + 2 * crt_offset l_crt = min(l_fab, -padx / 2) - crt_offset t_crt = t_fab - crt_offset # Pin 1 maker l_pin1 = l_slk + left_offset - padx / 2 - 2 * lw_slk h_pin1 = pin_bottom_offset + pady / 2 - lw_slk print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # create pads keepout=[] if not 1 in missing_pins: kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=pad, drill=ddrill, layers=['*.Cu', '*.Mask'])) keepout=keepout+addKeepoutRect(0,0,pad[0]+2*min_pad_distance+2*lw_slk, pad[1]+2*min_pad_distance+2*lw_slk) kicad_mod.append(Line(start=[-lw_fab/2, 0], end=[-lw_fab/2,-pin_bottom_offset], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[lw_fab/2, 0], end=[lw_fab/2,-pin_bottom_offset], layer='F.Fab', width=lw_fab)) for x in range(2, pins + 1): if not x in missing_pins: kicad_mod.append(Pad(number=x, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[(x - 1) * rm, 0], size=pad, drill=ddrill, layers=['*.Cu', '*.Mask'])) kicad_mod.append(Line(start=[(x - 1) * rm-lw_fab/2, 0], end=[(x - 1) * rm-lw_fab/2,-pin_bottom_offset], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[(x - 1) * rm+lw_fab/2, 0], end=[(x - 1) * rm+lw_fab/2,-pin_bottom_offset], layer='F.Fab', width=lw_fab)) if (padx/pady)<1.05 and (padx/pady)>.95: keepout=keepout+addKeepoutRect((x - 1) * rm,0,pad[0]+2*min_pad_distance+2*lw_slk, pad[1]+2*min_pad_distance+2*lw_slk) else: keepout=keepout+addKeepoutRound((x - 1) * rm,0,pad[0]+2*min_pad_distance+2*lw_slk, pad[1]+2*min_pad_distance+2*lw_slk) # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[(pins-1) / 2 * rm, min(-pady/2,t_slk) - txt_offset], layer='F.SilkS')) kicad_mod.append(Text(type='user', text='%R', at=[(pins-1) / 2 * rm, t_fab +h_fab/2], layer='F.Fab')) kicad_mod.append(Text(type='value', text=footprint_name, at=[(pins-1) / 2 * rm, pady/2 + txt_offset], layer='F.Fab')) # create FAB-layer pin1size=min(1, h_fab/2) bevelRectBL(kicad_mod, x=[l_fab, t_fab], size=[w_fab, h_fab], bevel_size=pin1size, layer='F.Fab', width=lw_fab) # create SILKSCREEN-layer addRectWithKeepout(kicad_mod, l_slk, t_slk, w_slk, h_slk, keepouts=keepout, layer='F.SilkS', width=lw_slk) addPolyLineWithKeepout(kicad_mod, [ [l_pin1, t_slk + h_slk], [l_pin1, t_slk + h_slk + h_pin1] ], layer='F.SilkS', width=lw_slk) # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt)], layer='F.CrtYd', width=lw_crt)) # add model kicad_mod.append(Model(filename="${KISYS3DMOD}/"+lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0, 0, 0], scale=[1,1,1], rotate=[0, 0, 0])) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') def makeResistorSIP(pins, footprint_name, description): rm = 2.54 h = 2.5 leftw = 1.29 ddrill = 0.8 padx = 1.6 pady = 1.6 w = (pins - 1) * rm + 2 * leftw left = -leftw top = -h / 2 h_slk = max(h, pady) + 2 * slk_offset w_slk = w + 2 * slk_offset l_slk = -leftw - slk_offset r_slk = l_slk + w_slk t_slk = -h_slk / 2 w_crt = w_slk + 2 * crt_offset h_crt = max(h_slk, pady) + 2 * crt_offset l_crt = min(l_slk, -padx / 2) - crt_offset t_crt = min(t_slk, -pady / 2) - crt_offset lib_name = "Resistors_ThroughHole" print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags("R") # set general values kicad_mod.append(Text(type='reference', text='REF**', at=[pins / 2 * rm, t_slk - txt_offset], layer='F.SilkS')) kicad_mod.append(Text(type='value', text=footprint_name, at=[pins / 2 * rm, h_slk / 2 + txt_offset], layer='F.Fab')) # create FAB-layer kicad_mod.append(RectLine(start=[left, top], end=[left + w, top + h], layer='F.Fab', width=lw_fab)) kicad_mod.append(Line(start=[0.5 * rm, top], end=[0.5 * rm, top + h], layer='F.Fab', width=lw_fab)) # create SILKSCREEN-layer kicad_mod.append(RectLine(start=[l_slk, t_slk], end=[l_slk + w_slk, t_slk + h_slk], layer='F.SilkS')) kicad_mod.append(Line(start=[0.5 * rm, t_slk], end=[0.5 * rm, t_slk + h_slk], layer='F.SilkS')) # create courtyard kicad_mod.append( RectLine(start=[roundCrt(l_crt), roundCrt(t_crt)], end=[roundCrt(l_crt + w_crt), roundCrt(t_crt + h_crt)], layer='F.CrtYd', width=lw_crt)) # create pads kicad_mod.append(Pad(number=1, type=Pad.TYPE_THT, shape=Pad.SHAPE_RECT, at=[0, 0], size=[padx, pady], drill=ddrill, layers=['*.Cu', '*.Mask'])) for x in range(2, pins + 1): kicad_mod.append(Pad(number=x, type=Pad.TYPE_THT, shape=Pad.SHAPE_OVAL, at=[(x - 1) * rm, 0], size=[padx, pady], drill=ddrill, layers=['*.Cu', '*.Mask'])) # add model kicad_mod.append(Model(filename="${KISYS3DMOD}/"+lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0, 0, 0], scale=[1 / 2.54, 1 / 2.54, 1 / 2.54], rotate=[0, 0, 0])) # print render tree # print(kicad_mod.getRenderTree()) # print(kicad_mod.getCompleteRenderTree()) # write file file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(footprint_name + '.kicad_mod') ================================================ FILE: scripts/tools/footprint_scripts_terminal_blocks.py ================================================ #!/usr/bin/env python import sys import os import math # ensure that the kicad-footprint-generator directory is available #sys.path.append(os.environ.get('KIFOOTPRINTGENERATOR')) # enable package import from parent directory #sys.path.append("D:\hardware\KiCAD\kicad-footprint-generator") # enable package import from parent directory sys.path.append(os.path.join(sys.path[0],"..","..","kicad_mod")) # load kicad_mod path sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from drawing_tools import * # NOQA from math import sqrt crt_offset = 0.5 # different for connectors slk_offset = lw_slk # # +----------------------------------------+ ^ # | H H H | ^ | # | | | | # | OOO OOO OOO | |secondHoleOffset | package_height # | OOOOO OOOOO OOOOO | v | ^ # | OOO OOO OOO | | | # +----------------------------------------+ ^ | | leftbottom_offset # | | | bevel_height | | # +----------------------------------------+ v v v # <--- rm ----> # <------>leftbottom_offset[0] <------->leftbottom_offset[2] (or leftbottom_offset[0] if len(leftbottom_offset)==2) # # # def makeTerminalBlockStd(footprint_name, pins, rm, package_height, leftbottom_offset, ddrill, pad, screw_diameter, bevel_height, slit_screw=True, screw_pin_offset=[0,0], secondHoleDiameter=0, secondHoleOffset=[0,0], thirdHoleDiameter=0, thirdHoleOffset=[0,0], fourthHoleDiameter=0, fourthHoleOffset=[0,0],secondDrillDiameter=0,secondDrillOffset=[0,0],secondDrillPad=[0,0],nibbleSize=[],nibblePos=[], fabref_offset=[0,0], stackable=False, tags_additional=[], lib_name="${{KISYS3DMOD}}/Connectors_Terminal_Blocks", classname="Connectors_Terminal_Blocks", classname_description="terminal block", webpage="", script_generated_note=""): package_size=[2*leftbottom_offset[0]+(pins-1)*rm, package_height]; if len(leftbottom_offset)==3: package_size=[leftbottom_offset[0]+leftbottom_offset[2]+(pins-1)*rm, package_height]; h_fab = package_size[1] w_fab = package_size[0] l_fab = -leftbottom_offset[0] t_fab = -(h_fab-leftbottom_offset[1]) h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset h_crt = h_fab + 2 * crt_offset w_crt = w_fab + (0 if stackable else 2 * crt_offset) l_crt = l_fab - (0 if stackable else crt_offset) t_crt = t_fab - crt_offset text_size = w_fab*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 description = "{2}, {0:d} pins, pitch {1:.3g}mm, size {3:.3g}x{4:.3g}mm^2, drill diamater {5:.3g}mm, pad diameter {6:.3g}mm, see {7:s}"\ .format(pins, rm, classname_description, package_size[0], package_size[1], ddrill, max(pad), webpage) tags = "THT {2} pitch {1:.3g}mm size {3:.3g}x{4:.3g}mm^2 drill {5:.3g}mm pad {6:.3g}mm"\ .format(pins, rm, classname_description, package_size[0], package_size[1], ddrill, max(pad)) if len(script_generated_note)>0: description=description+", "+script_generated_note if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset=[0,0] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.SilkS')) if (type(fabref_offset) in (tuple, list)): kicad_modg.append(Text(type='user', text='%R', at=[l_fab+w_fab/2+fabref_offset[0], t_fab+h_fab/2+fabref_offset[1]], layer='F.Fab', size=text_size ,thickness=text_t)) else: kicad_modg.append(Text(type='user', text='%R', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.Fab', size=text_size ,thickness=text_t)) kicad_modg.append(Text(type='value', text=footprint_name, at=[l_fab+w_fab/2, t_slk + h_slk + txt_offset], layer='F.Fab')) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_CIRCLE if pad[0] != pad[1]: pad_shapeother = Pad.SHAPE_OVAL extradrill1_type = Pad.TYPE_NPTH if secondDrillPad[0] > secondDrillDiameter or secondDrillPad[1] > secondDrillDiameter: extradrill1_type = Pad.TYPE_THT if secondDrillDiameter>0: if secondDrillPad[0] < secondDrillDiameter: secondDrillPad[0] = secondDrillDiameter if secondDrillPad[1] < secondDrillDiameter: secondDrillPad[1] = secondDrillDiameter pad_shape_extra = Pad.SHAPE_CIRCLE if secondDrillPad[0] != secondDrillPad[1]: pad_shape_extra = Pad.SHAPE_OVAL pad_layers = Pad.LAYERS_THT keepouts=[]; for p in range(1, pins + 1): pextra=0 if secondDrillPad[0]>0: pextra=p if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) if secondDrillDiameter>0: if extradrill1_type == Pad.TYPE_NPTH: num = "" extra_shape = pad_shape_extra else: num = p extra_shape = Pad.SHAPE_RECT kicad_modg.append(Pad(number=num, type=extradrill1_type, shape=extra_shape, at=[x1+secondDrillOffset[0], y1+secondDrillOffset[1]], size=secondDrillPad, drill=secondDrillDiameter, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1+secondDrillOffset[0], y1+secondDrillOffset[1], max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset, max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset) else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) if secondDrillPad[0]!=secondDrillPad[1]: keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) else: keepouts=keepouts+addKeepoutRound(x1, y1, pad[0]+8*slk_offset, pad[0]+8*slk_offset) if secondDrillDiameter>0: if extradrill1_type == Pad.TYPE_NPTH: num = "" else: num = p kicad_modg.append(Pad(number=num, type=extradrill1_type, shape=pad_shape_extra, at=[x1+secondDrillOffset[0], y1+secondDrillOffset[1]], size=secondDrillPad, drill=secondDrillDiameter, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1+secondDrillOffset[0], y1+secondDrillOffset[1], max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset, max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset) x1=x1+rm # create Body if len(bevel_height)>0: chamfer = min(h_fab/4, 2, bevel_height[0]) else: chamfer = min(h_fab/4, 2) bevelRectBL(kicad_modg, [l_fab,t_fab], [w_fab,h_fab], 'F.Fab', lw_fab, bevel_size=chamfer) for bh in bevel_height: kicad_modg.append(Line(start=[l_fab, t_fab + h_fab-bh], end=[l_fab+w_fab, t_fab + h_fab-bh], layer='F.Fab', width=lw_fab)) addHLineWithKeepout(kicad_modg,l_slk, l_slk+w_slk, t_fab + h_fab-bh, layer='F.SilkS', width=lw_slk, keepouts=keepouts) addRectWithKeepout(kicad_modg, l_slk, t_slk, w_slk, h_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts) # screws + other repeated features if screw_diameter>0: for p in range(1,pins+1): if screw_diameter>0: if slit_screw: addSlitScrew(kicad_modg, (p-1)*rm+screw_pin_offset[0], 0+screw_pin_offset[1], screw_diameter/2, 'F.Fab', lw_fab, roun=0.001) addSlitScrewWithKeepouts(kicad_modg, (p-1)*rm+screw_pin_offset[0], 0+screw_pin_offset[1], screw_diameter/2+3*slk_offset, 'F.SilkS', lw_slk, keepouts, roun=0.001) else: addCrossScrew(kicad_modg, (p-1)*rm+screw_pin_offset[0], 0+screw_pin_offset[1], screw_diameter/2, 'F.Fab', lw_fab, roun=0.001) addCrossScrewWithKeepouts(kicad_modg, (p-1)*rm+screw_pin_offset[0], 0+screw_pin_offset[1], screw_diameter/2+3*slk_offset, 'F.SilkS', lw_slk, keepouts, roun=0.001) if not (type(secondHoleDiameter) in (tuple, list)) and secondHoleDiameter>0 and (p-1)*rm+secondHoleOffset[0]0 and (p-1)*rm+thirdHoleOffset[0]0 and (p-1)*rm+fourthHoleOffset[0] # <------>leftbottom_offset[0] <------->leftbottom_offset[2] (or leftbottom_offset[0] if len(leftbottom_offset)==2) # <---------> opening[0] # # def makeTerminalBlockVertical(footprint_name, pins, rm, package_height, leftbottom_offset, ddrill, pad, opening, opening_yoffset, bevel_height, opening_xoffset=0, secondHoleDiameter=0, secondHoleOffset=[0,0], thirdHoleDiameter=0, thirdHoleOffset=[0,0], fourthHoleDiameter=0, fourthHoleOffset=[0,0],secondDrillDiameter=0,secondDrillOffset=[0,0],secondDrillPad=[0,0],nibbleSize=[],nibblePos=[], fabref_offset=[0,0], stackable=False, tags_additional=[], lib_name="${{KISYS3DMOD}}/Connectors_Terminal_Blocks", classname="Connectors_Terminal_Blocks", classname_description="terminal block", webpage="", script_generated_note=""): package_size=[2*leftbottom_offset[0]+(pins-1)*rm, package_height]; if len(leftbottom_offset)==3: package_size=[leftbottom_offset[0]+leftbottom_offset[2]+(pins-1)*rm, package_height]; h_fab = package_size[1] w_fab = package_size[0] l_fab = -leftbottom_offset[0] t_fab = -(h_fab-leftbottom_offset[1]) h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset h_crt = h_fab + 2 * crt_offset w_crt = w_fab + (0 if stackable else 2 * crt_offset) l_crt = l_fab - (0 if stackable else crt_offset) t_crt = t_fab - crt_offset text_size = w_fab*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 description = "{2}, vertical (cable from top), {0:d} pins, pitch {1:.3g}mm, size {3:.3g}x{4:.3g}mm^2, drill diamater {5:.3g}mm, pad diameter {6:.3g}mm, see {7}, script-generated with "\ .format(pins, rm, classname_description, package_size[0], package_size[1], ddrill, max(pad), webpage) tags = "THT {2} vertical pitch {1:.3g}mm size {3:.3g}x{4:.3g}mm^2 drill {5:.3g}mm pad {6:.3g}mm"\ .format(pins, rm, classname_description, package_size[0], package_size[1], ddrill, max(pad)) if len(script_generated_note)>0: description=description+", "+script_generated_note if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset=[0,0] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.SilkS')) if (type(fabref_offset) in (tuple, list)): kicad_modg.append(Text(type='user', text='%R', at=[l_fab+w_fab/2+fabref_offset[0], t_fab+h_fab/2+fabref_offset[1]], layer='F.Fab', size=text_size ,thickness=text_t)) else: kicad_modg.append(Text(type='user', text='%R', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.Fab', size=text_size ,thickness=text_t)) kicad_modg.append(Text(type='value', text=footprint_name, at=[l_fab+w_fab/2, t_slk + h_slk + txt_offset], layer='F.Fab')) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_CIRCLE if pad[0] != pad[1]: pad_shapeother = Pad.SHAPE_OVAL extradrill1_type = Pad.TYPE_NPTH if secondDrillPad[0] > secondDrillDiameter or secondDrillPad[1] > secondDrillDiameter: extradrill1_type = Pad.TYPE_THT if secondDrillDiameter>0: if secondDrillPad[0] < secondDrillDiameter: secondDrillPad[0] = secondDrillDiameter if secondDrillPad[1] < secondDrillDiameter: secondDrillPad[1] = secondDrillDiameter pad_shape_extra = Pad.SHAPE_CIRCLE if secondDrillPad[0] != secondDrillPad[1]: pad_shape_extra = Pad.SHAPE_OVAL pad_layers = Pad.LAYERS_THT keepouts=[]; for p in range(1, pins + 1): if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) if secondDrillDiameter>0: if extradrill1_type == Pad.TYPE_NPTH: num = "" extra_shape = pad_shape_extra else: num = p extra_shape = Pad.SHAPE_RECT kicad_modg.append(Pad(number=num, type=extradrill1_type, shape=extra_shape, at=[x1+secondDrillOffset[0], y1+secondDrillOffset[1]], size=secondDrillPad, drill=secondDrillDiameter, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1+secondDrillOffset[0], y1+secondDrillOffset[1], max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset, max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset) else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) if pad[0]!=pad[1]: keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) else: keepouts=keepouts+addKeepoutRound(x1, y1, pad[0]+8*slk_offset, pad[0]+8*slk_offset) if secondDrillDiameter>0: if extradrill1_type == Pad.TYPE_NPTH: num = "" else: num = p kicad_modg.append(Pad(number=num, type=extradrill1_type, shape=pad_shape_extra, at=[x1+secondDrillOffset[0], y1+secondDrillOffset[1]], size=secondDrillPad, drill=secondDrillDiameter, layers=pad_layers)) if secondDrillPad[0]!=secondDrillPad[1]: keepouts=keepouts+addKeepoutRect(x1+secondDrillOffset[0], y1+secondDrillOffset[1], max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset, max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset) else: keepouts=keepouts+addKeepoutRound(x1+secondDrillOffset[0], y1+secondDrillOffset[1], max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset, max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset) x1=x1+rm # create Body if len(bevel_height)>0: chamfer = min(h_fab/4, 2, bevel_height[0]) else: chamfer = min(h_fab/4, 2) bevelRectBL(kicad_modg, [l_fab,t_fab], [w_fab,h_fab], 'F.Fab', lw_fab, bevel_size=chamfer) for bh in bevel_height: kicad_modg.append(Line(start=[l_fab, t_fab + h_fab-bh], end=[l_fab+w_fab, t_fab + h_fab-bh], layer='F.Fab', width=lw_fab)) addHLineWithKeepout(kicad_modg,l_slk, l_slk+w_slk, t_fab + h_fab-bh, layer='F.SilkS', width=lw_slk, keepouts=keepouts) addRectWithKeepout(kicad_modg, l_slk, t_slk, w_slk, h_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts) # opening + other repeated features for p in range(1,pins+1): addRectWithKeepout(kicad_modg, (p-1)*rm-opening[0]/2-opening_xoffset, t_fab+h_fab-opening_yoffset-opening[1], opening[0], opening[1], 'F.SilkS', lw_slk, keepouts) addRectWith(kicad_modg, (p-1)*rm-opening[0]/2-opening_xoffset, t_fab+h_fab-opening_yoffset-opening[1], opening[0], opening[1], 'F.Fab', lw_fab) if not (type(secondHoleDiameter) in (tuple, list)) and secondHoleDiameter>0 and (p-1)*rm+secondHoleOffset[0]0 and (p-1)*rm+thirdHoleOffset[0]0 and (p-1)*rm+fourthHoleOffset[0] vsegment_lines_offset # +-+------------+-----------+-------------+ ^ # | | H | H | H | ^ | # | |----------- | | | | | ^ # | || OOO | | OOO | OOO | |secondHoleOffset | package_height | # | || OOOOO | | OOOOO | OOOOO | v | ^ | opening[1] # | || OOO | | OOO | OOO | | | | # +-+------------+-----------+-------------+ ^ | | leftbottom_offset x # | | | | | | bevel_height | | | opening_yoffset # +-+------------+-----------+-------------+ v v v v # <--- rm ----> # <------>leftbottom_offset[0] <------->leftbottom_offset[2] (or leftbottom_offset[0] if len(leftbottom_offset)==2) # <---------> opening[0] # # def makeTerminalBlock45Degree(footprint_name, pins, rm, package_height, leftbottom_offset, ddrill, pad, opening, opening_xoffset, opening_yoffset, opening_elliptic=False, bevel_height=[], vsegment_lines_offset=[], secondHoleDiameter=0, secondHoleOffset=[0,0], thirdHoleDiameter=0, thirdHoleOffset=[0,0], fourthHoleDiameter=0, fourthHoleOffset=[0,0], fifthHoleDiameter=0, fifthHoleOffset=[0,0],secondDrillDiameter=0,secondDrillOffset=[0,0],secondDrillPad=[0,0],nibbleSize=[],nibblePos=[], fabref_offset=[0,0],secondEllipseSize=[0,0],secondEllipseOffset=[0,0], stackable=False, tags_additional=[], lib_name="${{KISYS3DMOD}}/Connectors_Terminal_Blocks", classname="Connectors_Terminal_Blocks", classname_description="terminal block", webpage="", script_generated_note=""): package_size=[2*leftbottom_offset[0]+(pins-1)*rm, package_height]; if len(leftbottom_offset)==3: package_size=[leftbottom_offset[0]+leftbottom_offset[2]+(pins-1)*rm, package_height]; h_fab = package_size[1] w_fab = package_size[0] l_fab = -leftbottom_offset[0] t_fab = -(h_fab-leftbottom_offset[1]) h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset h_crt = h_fab + 2 * crt_offset w_crt = w_fab + (0 if stackable else 2 * crt_offset) l_crt = l_fab - (0 if stackable else crt_offset) t_crt = t_fab - crt_offset text_size = w_fab*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 description = "{2}, 45Degree (cable under 45degree), {0:d} pins, pitch {1:.3g}mm, size {3:.3g}x{4:.3g}mm^2, drill diamater {5:.3g}mm, pad diameter {6:.3g}mm, see {7}, script-generated with "\ .format(pins, rm,classname_description, package_size[0], package_size[1], ddrill, max(pad), webpage) tags = "THT {2} 45Degree pitch {1:.3g}mm size {3:.3g}x{4:.3g}mm^2 drill {5:.3g}mm pad {6:.3g}mm"\ .format(pins, rm,classname_description, package_size[0], package_size[1], ddrill, max(pad)) if len(script_generated_note)>0: description=description+", "+script_generated_note if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset=[0,0] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.SilkS')) if (type(fabref_offset) in (tuple, list)): kicad_modg.append(Text(type='user', text='%R', at=[l_fab+w_fab/2+fabref_offset[0], t_fab+h_fab/2+fabref_offset[1]], layer='F.Fab', size=text_size ,thickness=text_t)) else: kicad_modg.append(Text(type='user', text='%R', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.Fab', size=text_size ,thickness=text_t)) kicad_modg.append(Text(type='value', text=footprint_name, at=[l_fab+w_fab/2, t_slk + h_slk + txt_offset], layer='F.Fab')) # create pads p1 = int(1) x1 = 0 y1 = 0 pad_type = Pad.TYPE_THT pad_shape1 = Pad.SHAPE_RECT pad_shapeother = Pad.SHAPE_CIRCLE if pad[0] != pad[1]: pad_shapeother = Pad.SHAPE_OVAL extradrill1_type = Pad.TYPE_NPTH if secondDrillPad[0] > secondDrillDiameter or secondDrillPad[1] > secondDrillDiameter: extradrill1_type = Pad.TYPE_THT if secondDrillDiameter>0: if secondDrillPad[0] < secondDrillDiameter: secondDrillPad[0] = secondDrillDiameter if secondDrillPad[1] < secondDrillDiameter: secondDrillPad[1] = secondDrillDiameter pad_shape_extra = Pad.SHAPE_CIRCLE if secondDrillPad[0] != secondDrillPad[1]: pad_shape_extra = Pad.SHAPE_OVAL pad_layers = Pad.LAYERS_THT keepouts=[]; for p in range(1, pins + 1): pextra=0 if secondDrillPad[0]>0: pextra=p if p == 1: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shape1, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) if secondDrillDiameter>0: if extradrill1_type == Pad.TYPE_NPTH: num = "" extra_shape = pad_shape_extra else: num = p extra_shape = Pad.SHAPE_RECT kicad_modg.append(Pad(number=num, type=extradrill1_type, shape=extra_shape, at=[x1+secondDrillOffset[0], y1+secondDrillOffset[1]], size=secondDrillPad, drill=secondDrillDiameter, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1+secondDrillOffset[0], y1+secondDrillOffset[1], max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset, max(secondDrillPad[1],secondDrillDiameter)+8*slk_offset) else: kicad_modg.append(Pad(number=p, type=pad_type, shape=pad_shapeother, at=[x1, y1], size=pad, drill=ddrill, layers=pad_layers)) if pad[0]!=pad[1]: keepouts=keepouts+addKeepoutRect(x1, y1, pad[0]+8*slk_offset, pad[1]+8*slk_offset) else: keepouts=keepouts+addKeepoutRound(x1, y1, pad[0]+8*slk_offset, pad[0]+8*slk_offset) if secondDrillDiameter>0: if extradrill1_type == Pad.TYPE_NPTH: num = "" else: num = p kicad_modg.append(Pad(number=num, type=extradrill1_type, shape=pad_shape_extra, at=[x1+secondDrillOffset[0], y1+secondDrillOffset[1]], size=secondDrillPad, drill=secondDrillDiameter, layers=pad_layers)) keepouts=keepouts+addKeepoutRect(x1+secondDrillOffset[0], y1+secondDrillOffset[1], max(secondDrillPad[0],secondDrillDiameter)+8*slk_offset, max(secondDrillPad[1],secondDrillDiameter)+8*slk_offset) x1=x1+rm # create Body if len(bevel_height)>0: chamfer = min(h_fab/4, 2, bevel_height[0]) else: chamfer = min(h_fab/4, 2) bevelRectBL(kicad_modg, [l_fab,t_fab], [w_fab,h_fab], 'F.Fab', lw_fab, bevel_size=chamfer) for bh in bevel_height: kicad_modg.append(Line(start=[l_fab, t_fab + h_fab-bh], end=[l_fab+w_fab, t_fab + h_fab-bh], layer='F.Fab', width=lw_fab)) addHLineWithKeepout(kicad_modg,l_slk, l_slk+w_slk, t_fab + h_fab-bh, layer='F.SilkS', width=lw_slk, keepouts=keepouts) addRectWithKeepout(kicad_modg, l_slk, t_slk, w_slk, h_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts) # opening + other repeated features for p in range(1,pins+1): if opening[0]>0 and opening[1]>0: if opening_elliptic: addEllipse(kicad_modg, (p-1)*rm+opening_xoffset, t_fab+h_fab-opening_yoffset, opening[0], opening[1], layer='F.Fab', width=lw_fab) addEllipseWithKeepout(kicad_modg, (p-1)*rm+opening_xoffset, t_fab+h_fab-opening_yoffset, opening[0], opening[1], layer='F.SilkS', width=lw_slk, keepouts=keepouts) else: addRectWithKeepout(kicad_modg, (p-1)*rm-opening[0]/2+opening_xoffset, t_fab+h_fab-opening_yoffset-opening[1], opening[0], opening[1], 'F.SilkS', lw_slk, keepouts) addRectWith(kicad_modg, (p-1)*rm-opening[0]/2+opening_xoffset, t_fab+h_fab-opening_yoffset-opening[1], opening[0], opening[1], 'F.Fab', lw_fab) # vertical segment separation lines for seg_offset in vsegment_lines_offset: if seg_offset>=l_fab and seg_offset<=l_fab+w_fab: addVLineWithKeepout(kicad_modg, x=(p-1)*rm+seg_offset, y0=t_fab, y1=t_fab+h_fab, layer='F.Fab', width=lw_fab, keepouts=[]) addVLineWithKeepout(kicad_modg, x=(p-1)*rm+seg_offset, y0=t_slk, y1=t_slk+h_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts) if not (type(secondHoleDiameter) in (tuple, list)) and secondHoleDiameter>0 and (p-1)*rm+secondHoleOffset[0]0 and (p-1)*rm+thirdHoleOffset[0]0 and (p-1)*rm+fourthHoleOffset[0]0 and (p-1)*rm+fifthHoleOffset[0]0 and secondEllipseSize[1]>0: addEllipse(kicad_modg, (p-1)*rm+secondEllipseOffset[0], 0+secondEllipseOffset[1], secondEllipseSize[0], secondEllipseSize[1], layer='F.Fab', width=lw_fab) addEllipseWithKeepout(kicad_modg, (p-1)*rm+secondEllipseOffset[0], 0+secondEllipseOffset[1], secondEllipseSize[0], secondEllipseSize[1], layer='F.SilkS', width=lw_slk, keepouts=keepouts) #nibble if len(nibbleSize)==2 and len(nibblePos)==2: kicad_modg.append(RectLine(start=[l_fab+nibblePos[0], t_fab+nibblePos[1]], end=[l_fab+nibblePos[0]+nibbleSize[0], t_fab+nibblePos[1]+nibbleSize[1]], layer='F.Fab', width=lw_fab)) addRectWithKeepout(kicad_modg, l_fab+nibblePos[0]-slk_offset, t_fab+nibblePos[1]-slk_offset, nibbleSize[0],nibbleSize[1]+2*slk_offset, 'F.SilkS', lw_slk, keepouts) # create SILKSCREEN-pin1-marker kicad_modg.append(Line(start=[l_slk-2*lw_slk, t_slk + h_slk-chamfer], end=[l_slk-2*lw_slk, t_slk + h_slk+2*lw_slk], layer='F.SilkS', width=lw_slk)) kicad_modg.append(Line(start=[l_slk-2*lw_slk, t_slk + h_slk+2*lw_slk], end=[l_slk-2*lw_slk+chamfer, t_slk + h_slk+2*lw_slk], layer='F.SilkS', width=lw_slk)) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # add model kicad_modg.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0,0,0], scale=[1,1,1], rotate=[0,0,0])) #debug_draw_keepouts(kicad_modg,keepouts) # write file if "/" in lib_name: fp_lib_name = lib_name.split('/')[-1] elif "\\" in lib_name: fp_lib_name = lib_name.split('\\')[-1] output_dir = fp_lib_name + '.pretty' + os.sep if not os.path.isdir(output_dir): os.makedirs(output_dir) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(output_dir + footprint_name + '.kicad_mod') # pins [[x,y], [x,y], ...] location of pins (relative to center of block) # ddrill: drill diameter for pins # pad [padx,pady]: size of pin-pad # screw_diameter: diameter of screw # screw_offset: offset of screw from package center # slit_screw=true|False: type of screw # block_size [w,h]: size of block def makeScrewTerminalSingleStd(footprint_name, block_size, block_offset, pins, ddrill, pad, screw_diameter, screw_offset, slit_screw=True, tags_additional=[], lib_name="${{KISYS3DMOD}}/Connectors_Terminal_Blocks", classname="Connectors_Terminal_Blocks", classname_description="single screw terminal terminal block", webpage="", script_generated_note=""): h_fab = block_size[1] w_fab = block_size[0] l_fab = -block_size[0]/2+block_offset[0] t_fab = -block_size[1]/2+block_offset[1] h_slk = h_fab + 2 * slk_offset w_slk = w_fab + 2 * slk_offset l_slk = l_fab - slk_offset t_slk = t_fab - slk_offset h_crt = h_fab + 2 * crt_offset w_crt = w_fab + 2 * crt_offset l_crt = l_fab - crt_offset t_crt = t_fab - crt_offset text_size = w_fab*0.6 fab_text_size_max = 1.0 if text_size < fab_text_size_min: text_size = fab_text_size_min elif text_size > fab_text_size_max: text_size = fab_text_size_max text_size = round(text_size, 2) text_size = [text_size,text_size] text_t = text_size[0] * 0.15 txt_offset=text_size[1] description = "{2}, block size {3:.3g}x{4:.3g}mm^2, drill diamater {5:.3g}mm, {1:d} pads, pad diameter {6:.3g}mm, see {7}"\ .format(0, len(pins), classname_description, block_size[0], block_size[1], ddrill, max(pad), webpage) tags = "THT {2} size {3:.3g}x{4:.3g}mm^2 drill {5:.3g}mm pad {6:.3g}mm"\ .format(0, len(pins), classname_description, block_size[0], block_size[1], ddrill, max(pad)) if len(script_generated_note)>0: description=description+", "+script_generated_note if (len(tags_additional) > 0): for t in tags_additional: footprint_name = footprint_name + "_" + t description = description + ", " + t tags = tags + " " + t print(footprint_name) # init kicad footprint kicad_mod = Footprint(footprint_name) kicad_mod.setDescription(description) kicad_mod.setTags(tags) # anchor for SMD-symbols is in the center, for THT-sybols at pin1 offset=pins[0] kicad_modg = Translation(offset[0], offset[1]) kicad_mod.append(kicad_modg) # set general values kicad_modg.append(Text(type='reference', text='REF**', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.SilkS')) kicad_modg.append(Text(type='user', text='%R', at=[l_fab+w_fab/2, t_slk - txt_offset], layer='F.Fab')) kicad_modg.append(Text(type='value', text=footprint_name, at=[l_fab+w_fab/2, t_slk + h_slk + txt_offset], layer='F.Fab')) # create pads p1 = int(1) x1 = 0 y1 = 0 # pins/pads pad_type = Pad.TYPE_THT pad_shapeother = Pad.SHAPE_CIRCLE pad_layers = Pad.LAYERS_THT keepouts=[]; for p in pins: kicad_modg.append(Pad(number=1, type=pad_type, shape=pad_shapeother, at=p, size=pad, drill=ddrill, layers=pad_layers)) keepouts=keepouts+addKeepoutRound(p[0], p[1], pad[0]+8*slk_offset, pad[0]+8*slk_offset) # screw keepouts_screw=[]; if screw_diameter>0: keepouts_screw=keepouts_screw+addKeepoutRound(screw_offset[0], screw_offset[1], screw_diameter, screw_diameter) if slit_screw: addSlitScrew(kicad_modg, screw_offset[0], screw_offset[1], screw_diameter/2, 'F.Fab', lw_fab) addSlitScrewWithKeepouts(kicad_modg, screw_offset[0], screw_offset[1], screw_diameter/2+1*slk_offset, 'F.SilkS', lw_slk, keepouts) else: addCrossScrew(kicad_modg, screw_offset[0], screw_offset[1], screw_diameter/2, 'F.Fab', lw_fab) addCrossScrewWithKeepouts(kicad_modg, screw_offset[0], screw_offset[1], screw_diameter/2+1*slk_offset, 'F.SilkS', lw_slk, keepouts) # create Body addRectWithKeepout(kicad_modg, l_fab, t_fab, w_fab, h_fab, layer='F.Fab', width=lw_fab, keepouts=keepouts_screw) addRectWithKeepout(kicad_modg, l_slk, t_slk, w_slk, h_slk, layer='F.SilkS', width=lw_slk, keepouts=keepouts+keepouts_screw) # create courtyard kicad_mod.append(RectLine(start=[roundCrt(l_crt + offset[0]), roundCrt(t_crt + offset[1])], end=[roundCrt(l_crt + offset[0] + w_crt), roundCrt(t_crt + offset[1] + h_crt)], layer='F.CrtYd', width=lw_crt)) # add model kicad_modg.append( Model(filename=lib_name + ".3dshapes/" + footprint_name + ".wrl", at=[0,0,0], scale=[1,1,1], rotate=[0,0,0])) #debug_draw_keepouts(kicad_modg,keepouts) # write file if "/" in lib_name: fp_lib_name = lib_name.split('/')[-1] elif "\\" in lib_name: fp_lib_name = lib_name.split('\\')[-1] output_dir = fp_lib_name + '.pretty' + os.sep if not os.path.isdir(output_dir): os.makedirs(output_dir) file_handler = KicadFileHandler(kicad_mod) file_handler.writeFile(output_dir + footprint_name + '.kicad_mod') ================================================ FILE: scripts/tools/footprint_text_fields.py ================================================ import sys, os sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA def _roundToBase(value, base): return round(value/base) * base def _getTextFieldDetails(field_definition, body_edges, courtyard, text_y_inside_position = 'center', allow_rotation = False): body_size = [body_edges['right'] - body_edges['left'], body_edges['bottom'] - body_edges['top']] body_center = [(body_edges['right'] + body_edges['left'])/2, (body_edges['bottom'] + body_edges['top'])/2] position_y = field_definition['position_y'] at = body_center.copy() if body_size[0] < body_size[1] and allow_rotation and position_y == 'inside': rotation = 1 else: rotation = 0 if 'size' in field_definition: size = field_definition['size'] fontwidth = field_definition['fontwidth'] elif 'size_min' in field_definition and 'size_max' in field_definition: # We want at least 3 char reference designators space. If we can't fit these we move the reverence to the outside. size_max = field_definition['size_max'] size_min = field_definition['size_min'] if body_size[rotation] >= 4*size_max[1]: if body_size[0] >= 4*size_max[1]: rotation = 0 size = size_max elif body_size[rotation] < 4*size_min[1]: size = size_min if body_size[rotation] < 3*size_min[1]: if position_y == 'inside': rotation = 0 position_y = 'outside_top' else: fs = _roundToBase(body_size[rotation]/4, 0.01) size = [fs, fs] if size[1] > body_size[(rotation+1)%2]-0.2: fs = max(body_size[(rotation+1)%2]-0.2, size_min[1]) size = [fs, fs] fontwidth = _roundToBase(field_definition['thickness_factor']*size[0], 0.01) else: rotation = 0 position_y = 'outside_top' size = [1,1] fontwidth = 0.15 if position_y == 'inside': if text_y_inside_position == 'top': position_y = 'inside_top' elif text_y_inside_position == 'bottom': position_y = 'inside_bottom' elif text_y_inside_position == 'left': position_y = 'inside_left' elif text_y_inside_position == 'right': position_y = 'inside_right' elif isinstance(text_y_inside_position,int) or isinstance(text_y_inside_position,float): at[1] = text_y_inside_position text_edge_offset = size[0]/2+0.2 if position_y == 'outside_top': at = [body_center[0], courtyard['top']-text_edge_offset] elif position_y == 'inside_top': at = [body_center[0], body_edges['top']+text_edge_offset] elif position_y == 'inside_left': at = [body_edges['left'] + text_edge_offset, body_center[1]] rotation = 1 elif position_y == 'inside_right': at = [body_edges['right'] - text_edge_offset, body_center[1]] rotation = 1 elif position_y == 'outside_bottom': at = [body_center[0], courtyard['bottom']+text_edge_offset] elif position_y == 'inside_bottom': at = [body_center[0], body_edges['bottom']-text_edge_offset] at = [_roundToBase(at[0],0.01), _roundToBase(at[1],0.01)] return {'at': at, 'size': size, 'layer': field_definition['layer'], 'thickness': fontwidth, 'rotation': rotation*90} def addTextFields(kicad_mod, configuration, body_edges, courtyard, fp_name, text_y_inside_position = 'center', allow_rotation = False): reference_fields = configuration['references'] kicad_mod.append(Text(type='reference', text='REF**', **_getTextFieldDetails(reference_fields[0], body_edges, courtyard, text_y_inside_position, allow_rotation))) for additional_ref in reference_fields[1:]: kicad_mod.append(Text(type='user', text='%R', **_getTextFieldDetails(additional_ref, body_edges, courtyard, text_y_inside_position, allow_rotation))) value_fields = configuration['values'] kicad_mod.append(Text(type='value', text=fp_name, **_getTextFieldDetails(value_fields[0], body_edges, courtyard, text_y_inside_position, allow_rotation))) for additional_value in value_fields[1:]: kicad_mod.append(Text(type='user', text='%V', **_getTextFieldDetails(additional_value, body_edges, courtyard, text_y_inside_position, allow_rotation))) ================================================ FILE: scripts/tools/global_config_files/config_KLCv1.0.yaml ================================================ 3d_model_prefix: '${KISYS3DMOD}/' silk_line_width: 0.15 silk_pad_clearance: 0.2 silk_fab_offset: 0.15 silk_line_lenght_min: 0.4 allow_silk_below_part: 'tht' # tht | smd | all | none fab_line_width: 0.15 fab_pin1_marker_length: 1 courtyard_line_width: 0.05 courtyard_grid: 0.01 courtyard_offset: default: 0.25 connector: 0.5 bga: 1 edge_cuts_line_width: 0.12 references: - layer: 'F.Fab' position_y: 'top' # outside_top | inside | outside_bottom size: [2,2] fontwidth: 0.15 values: - layer: 'F.Fab' position_y: 'bottom' # outside_top | inside | outside_bottom size: [1,1] fontwidth: 0.15 ================================================ FILE: scripts/tools/global_config_files/config_KLCv2.0.yaml ================================================ 3d_model_prefix: '${KISYS3DMOD}/' silk_line_width: 0.12 silk_pad_clearance: 0.2 silk_fab_offset: 0.11 silk_line_lenght_min: 0.4 allow_silk_below_part: 'tht' # tht | smd | all | none fab_line_width: 0.1 fab_pin1_marker_length: 1 courtyard_line_width: 0.05 courtyard_grid: 0.01 courtyard_offset: default: 0.25 connector: 0.5 bga: 1 edge_cuts_line_width: 0.12 references: - layer: 'F.SilkS' position_y: 'top' # outside_top | inside | outside_bottom size: [1,1] fontwidth: 0.15 - layer: 'F.Fab' position_y: 'inside' # outside_top | inside | outside_bottom size_max: [1,1] size_min: [0.25, 0.25] thickness_factor: 0.15 # size: [1,1] # fontwidth: 0.15 values: - layer: 'F.Fab' position_y: 'bottom' # outside_top | inside | outside_bottom size: [1,1] fontwidth: 0.15 ================================================ FILE: scripts/tools/global_config_files/config_KLCv3.0.yaml ================================================ 3d_model_prefix: '${KISYS3DMOD}/' silk_line_width: 0.12 silk_pad_clearance: 0.2 silk_fab_offset: 0.11 silk_line_lenght_min: 0.2 allow_silk_below_part: 'tht' # tht | smd | all | none fab_line_width: 0.1 fab_pin1_marker_length: 1 fab_bevel_size_absolute: 1 # Bevel size of footprints in mm fab_bevel_size_relative: 0.25 # Bevel size of footprints relative to package size courtyard_line_width: 0.05 courtyard_grid: 0.01 courtyard_offset: default: 0.25 connector: 0.5 bga: 1 edge_cuts_line_width: 0.12 # IPC-7351C will most likely suggest the use of rounded rectangle pads # with 25% radius ratio but at a maximum of 0.25mm round_rect_max_radius: 0.25 round_rect_radius_ratio: 0.25 references: - layer: 'F.SilkS' position_y: 'outside_top' # outside_top | inside | outside_bottom size: [1,1] fontwidth: 0.15 - layer: 'F.Fab' position_y: 'inside' # outside_top | inside | outside_bottom size_max: [1,1] size_min: [0.25, 0.25] thickness_factor: 0.15 # size: [1,1] # fontwidth: 0.15 values: - layer: 'F.Fab' position_y: 'outside_bottom' # outside_top | inside | outside_bottom size: [1,1] fontwidth: 0.15 ================================================ FILE: scripts/tools/global_config_files/config_Tera.yaml ================================================ 3d_model_prefix: '${KISYS3DMOD}/' silk_line_width: 0.15 silk_pad_clearance: 0.2 silk_fab_offset: 0.11 silk_line_lenght_min: 0.4 allow_silk_below_part: 'tht' # tht | smd | all | none fab_line_width: 0.05 fab_pin1_marker_length: 1 courtyard_line_width: 0.05 courtyard_grid: 0.01 courtyard_offset: default: 0.25 connector: 0.5 bga: 1 edge_cuts_line_width: 0.12 references: - layer: 'F.Fab' position_y: 'inside' # outside_top | inside | outside_bottom # size: [1,1] # fontwidth: 0.15 size_max: [1,1] size_min: [0.5, 0.5] thickness_factor: 0.15 - layer: 'F.SilkS' position_y: 'outside_top' # outside_top | inside | outside_bottom size: [1,1] fontwidth: 0.15 values: - layer: 'F.Fab' position_y: 'outside_bottom' # outside_top | inside | outside_bottom size: [0.6, 0.6] fontwidth: 0.1 ================================================ FILE: scripts/tools/ipc_pad_size_calculators.py ================================================ from __future__ import division import math import re def roundToBase(value, base): return round(value/base) * base class TolerancedSize(): def to_metric(value, unit): if unit == "inch": factor = 25.4 elif unit == "mil": factor = 25.4/1000 else: factor = 1 return value * factor def __init__(self, minimum=None, nominal=None, maximum=None, tolerance=None, unit=None): if nominal is not None: self.nominal = nominal else: if minimum is None or maximum is None: raise KeyError("Either nominal or minimum and maximum must be given") self.nominal = (minimum + maximum)/2 if minimum is not None and maximum is not None: self.minimum = minimum self.maximum = maximum elif tolerance is not None: if type(tolerance) in [int, float]: self.minimum = self.nominal - tolerance self.maximum = self.nominal + tolerance elif len(tolerance) == 2: if tolerance[0] < 0: self.minimum = self.nominal + tolerance[0] self.maximum = self.nominal + tolerance[1] elif tolerance[1] < 0: self.minimum = self.nominal + tolerance[1] self.maximum = self.nominal + tolerance[0] else: self.minimum = self.nominal - tolerance[0] self.maximum = self.nominal + tolerance[1] else: self.minimum = self.nominal self.maximum = self.nominal if self.maximum < self.minimum: raise ValueError("Maximum is smaller than minimum. Tolerance ranges given wrong or parameters confused.") self.minimum = TolerancedSize.to_metric(self.minimum, unit) self.nominal = TolerancedSize.to_metric(self.nominal, unit) self.maximum = TolerancedSize.to_metric(self.maximum, unit) self.ipc_tol = self.maximum - self.minimum self.ipc_tol_RMS = self.ipc_tol self.maximum_RMS = self.maximum self.minimum_RMS = self.minimum def updateRMS(self, tolerances): ipc_tol_RMS = 0 for t in tolerances: ipc_tol_RMS += t**2 self.ipc_tol_RMS = math.sqrt(ipc_tol_RMS) if self.ipc_tol_RMS > self.ipc_tol: if roundToBase(self.ipc_tol_RMS, 1e-6) > roundToBase(self.ipc_tol, 1e-6): raise ValueError( "RMS tolerance larger than normal tolerance. Did you give the wrong tolerances?\ntol(RMS): {} tol: {}"\ .format(self.ipc_tol_RMS, self.ipc_tol)) # the discrepancy most likely comes from floating point errors. Ignore it. self.ipc_tol_RMS = self.ipc_tol self.maximum_RMS = self.maximum - (self.ipc_tol - self.ipc_tol_RMS)/2 self.minimum_RMS = self.minimum + (self.ipc_tol - self.ipc_tol_RMS)/2 def __add__(self, other): if type(other) in [int, float]: result = TolerancedSize( minimum = self.minimum + other, maximum = self.maximum + other ) return result result = TolerancedSize( minimum = self.minimum + other.minimum, maximum = self.maximum + other.maximum ) result.updateRMS([self.ipc_tol_RMS, other.ipc_tol_RMS]) return result def __sub__(self, other): if type(other) in [int, float]: result = TolerancedSize( minimum = self.minimum - other, maximum = self.maximum - other ) return result result = TolerancedSize( minimum = self.minimum - other.maximum, maximum = self.maximum - other.minimum ) result.updateRMS([self.ipc_tol_RMS, other.ipc_tol_RMS]) return result def __mul__(self, other): if type(other) not in [int, float]: raise NotImplementedError("Only multiplication with int and float is implemented right now.") result = TolerancedSize( minimum = self.minimum*other, maximum = self.maximum*other ) result.updateRMS([self.ipc_tol_RMS*math.sqrt(other)]) return result def __div__(self, other): return self.__truediv__(other) def __truediv__(self, other): if type(other) not in [int, float]: raise NotImplementedError("Only multiplication with int and float is implemented right now.") result = TolerancedSize( minimum = self.minimum/other, maximum = self.maximum/other ) result.updateRMS([self.ipc_tol_RMS/math.sqrt(other)]) return result def __floordiv__(self, other): if type(other) not in [int, float]: raise NotImplementedError("Only multiplication with int and float is implemented right now.") result = TolerancedSize( minimum = self.minimum//other, maximum = self.maximum//other ) result.updateRMS([self.ipc_tol_RMS//math.sqrt(other)]) return result @staticmethod def fromString(input, unit=None): minimum = None nominal = None maximum = None tolerance = None s = re.sub(r'\s+', '', str(input)) if type(input) in [int, float]: nominal = input elif "+/-" in s: tokens = s.split("+/-") nominal = float(tokens[0]) tolerance = float(tokens[1]) elif '+' in s and '-' in s: if s.count('+') > 1 or s.count('-') > 1: raise ValueError("Illegal dimension specifier: {}\n\tToo many tolerance specifiers. Expected nom+tolp-toln".format(input)) idxp = s.find('+') idxn = s.find('-') nominal = float(s[0:min(idxp, idxn)]) tolerance=[ float(s[idxn : idxp if idxnidxp else None])] elif '...' in s or '..' in s: s = s.replace('...', '..') tokens = s.split('..') if len(tokens) > 3: raise ValueError("Illegal dimension specifier: {}\n\tToo many tokens seperated by '...' (Valid options are min...max or min...nom...max)".format(input)) minimum = float(tokens[0]) maximum = float(tokens[-1]) if len(tokens) == 3: nominal = float(tokens[1]) else: try: nominal = float(s) except Exception as e: raise ValueError("Dimension specifier not recogniced: {}\n\t Valid options are nom, nom+/-tol, nom+tolp-toln, min...max or min...nom...max".format(input)) from e return TolerancedSize( minimum=minimum, nominal=nominal, maximum=maximum, tolerance=tolerance, unit=unit ) @staticmethod def fromYaml(yaml, base_name=None, unit=None): if base_name is not None: if base_name+"_min" in yaml or base_name+"_max" in yaml or base_name+"_tol" in yaml: return TolerancedSize( minimum=yaml.get(base_name+"_min"), nominal=yaml.get(base_name), maximum=yaml.get(base_name+"_max"), tolerance=yaml.get(base_name+"_tol") ) return TolerancedSize.fromYaml(yaml.get(base_name), unit=unit) elif type(yaml) is dict: return TolerancedSize( minimum=yaml.get("minimum"), nominal=yaml.get("nominal"), maximum=yaml.get("maximum"), tolerance=yaml.get("tolerance"), unit=unit ) else: return TolerancedSize.fromString(yaml, unit) def __str__(self): return 'nom: {}, min: {}, max: {} | min_rms: {}, max_rms: {}'.format(self.nominal, self.minimum, self.maximum, self.minimum_RMS, self.maximum_RMS) def ipc_body_edge_inside(ipc_data, ipc_round_base, manf_tol, body_size, lead_width, lead_len=None, lead_inside=None, heel_reduction=0): pull_back = TolerancedSize(nominal=0) return ipc_body_edge_inside_pull_back( ipc_data, ipc_round_base, manf_tol, body_size, lead_width, lead_len=lead_len, lead_inside=lead_inside, pull_back=pull_back, heel_reduction=heel_reduction ) def ipc_body_edge_inside_pull_back(ipc_data, ipc_round_base, manf_tol, body_size, lead_width, lead_len=None, lead_inside=None, body_to_inside_lead_edge=None, pull_back=None, lead_outside=None, heel_reduction=0): # Zmax = Lmin + 2JT + √(CL^2 + F^2 + P^2) # Gmin = Smax − 2JH − √(CS^2 + F^2 + P^2) # Xmax = Wmin + 2JS + √(CW^2 + F^2 + P^2) # Some manufacturers do not list the terminal spacing (S) in their datasheet but list the terminal lenght (T) # Then one can calculate # Stol(RMS) = √(Ltol^2 + 2*^2) # Smin = Lmin - 2*Tmax # Smax(RMS) = Smin + Stol(RMS) F = manf_tol.get('manufacturing_tolerance', 0.1) P = manf_tol.get('placement_tolerance', 0.05) if lead_outside is None: if pull_back is None: raise KeyError("Either lead outside or pull back distance must be given") lead_outside = body_size - pull_back*2 if lead_inside is not None: S = lead_inside elif lead_len is not None: S = lead_outside - lead_len*2 elif body_to_inside_lead_edge is not None: S = body_size - body_to_inside_lead_edge*2 else: raise KeyError("either lead inside distance, lead to body edge or lead lenght must be given") Gmin = S.maximum_RMS - 2*ipc_data['heel'] + 2*heel_reduction - math.sqrt(S.ipc_tol_RMS**2 + F**2 + P**2) Zmax = lead_outside.minimum_RMS + 2*ipc_data['toe'] + math.sqrt(lead_outside.ipc_tol_RMS**2 + F**2 + P**2) Xmax = lead_width.minimum_RMS + 2*ipc_data['side'] + math.sqrt(lead_width.ipc_tol_RMS**2 + F**2 + P**2) Zmax = roundToBase(Zmax, ipc_round_base['toe']) Gmin = roundToBase(Gmin, ipc_round_base['heel']) Xmax = roundToBase(Xmax, ipc_round_base['side']) return Gmin, Zmax, Xmax def ipc_gull_wing(ipc_data, ipc_round_base, manf_tol, lead_width, lead_outside, lead_len=None, lead_inside=None, heel_reduction=0): # Zmax = Lmin + 2JT + √(CL^2 + F^2 + P^2) # Gmin = Smax − 2JH − √(CS^2 + F^2 + P^2) # Xmax = Wmin + 2JS + √(CW^2 + F^2 + P^2) # Some manufacturers do not list the terminal spacing (S) in their datasheet but list the terminal lenght (T) # Then one can calculate # Stol(RMS) = √(Ltol^2 + 2*^2) # Smin = Lmin - 2*Tmax # Smax(RMS) = Smin + Stol(RMS) F = manf_tol.get('manufacturing_tolerance', 0.1) P = manf_tol.get('placement_tolerance', 0.05) if lead_inside is not None: S = lead_inside elif lead_len is not None: S = lead_outside - lead_len*2 else: raise KeyError("either lead inside distance or lead lenght must be given") Gmin = S.maximum_RMS - 2*ipc_data['heel'] + 2*heel_reduction - math.sqrt(S.ipc_tol_RMS**2 + F**2 + P**2) Zmax = lead_outside.minimum_RMS + 2*ipc_data['toe'] + math.sqrt(lead_outside.ipc_tol_RMS**2 + F**2 + P**2) Xmax = lead_width.minimum_RMS + 2*ipc_data['side'] + math.sqrt(lead_width.ipc_tol_RMS**2 + F**2 + P**2) Zmax = roundToBase(Zmax, ipc_round_base['toe']) Gmin = roundToBase(Gmin, ipc_round_base['heel']) Xmax = roundToBase(Xmax, ipc_round_base['side']) return Gmin, Zmax, Xmax def ipc_pad_center_plus_size(ipc_data, ipc_round_base, manf_tol, center_position, lead_length, lead_width): F = manf_tol.get('manufacturing_tolerance', 0.1) P = manf_tol.get('placement_tolerance', 0.05) S = center_position*2 - lead_length lead_outside = center_position*2 + lead_length Gmin = S.maximum_RMS - 2*ipc_data['heel'] - math.sqrt(S.ipc_tol_RMS**2 + F**2 + P**2) Zmax = lead_outside.minimum_RMS + 2*ipc_data['toe'] + math.sqrt(lead_outside.ipc_tol_RMS**2 + F**2 + P**2) Xmax = lead_width.minimum_RMS + 2*ipc_data['side'] + math.sqrt(lead_width.ipc_tol_RMS**2 + F**2 + P**2) Zmax = roundToBase(Zmax, ipc_round_base['toe']) Gmin = roundToBase(Gmin, ipc_round_base['heel']) Xmax = roundToBase(Xmax, ipc_round_base['side']) return Gmin, Zmax, Xmax ================================================ FILE: scripts/tools/pad_number_generators.py ================================================ """ Pad number generator functions. Some ICs have a non-standard pin numbering scheme. Using the generators an iterable is generated following the scheme. Available generators: ---------------------- - increment: Generates pin numbers increasing by one and supports skipping pin numbers using the deleted_pins kwarg (skipped pins return a bogus value of -1) - cw_dual: Generates pin numbers counting clockwise from the starting position - ccw_dual: Generates pin numbers counting counter-clockwise from the starting position Examples: --------- To use a generator add the following to the device config: pad_numbers: generator: 'ccw_dual' axis: 'x' """ def increment(pincount, init=1, **kwargs): i = init j = init # pad number for deleted pins if kwargs.get("deleted_pins"): skip_pins = kwargs["deleted_pins"] while i <= pincount: if kwargs.get("deleted_pins"): if i in skip_pins: yield None else: yield j j += 1 i += 1 # i acts like pin location for deleted pins else: yield i i += 1 def _get_pin_cw(pincount, loc): """Helper function to locate pin number for cw_dual. Args: pincount: Total number of pins loc: Starting location Returns: pin_number: Starting pin number """ pins_per_side = pincount // 2 if loc == "top_left": return 0 elif loc == "bottom_left": return pins_per_side * 2 + 1 elif loc == "bottom_right": return pins_per_side elif loc == "top_right": return pins_per_side + 1 return 0 def _get_pin_ccw(pincount, loc): """Helper function to locate pin number for ccw_dual. Args: pincount: Total number of pins loc: Starting location Returns: pin_number: Starting pin number """ pins_per_side = pincount // 2 if loc == "top_left": return 0 elif loc == "bottom_left": return pins_per_side + 1 elif loc == "bottom_right": return pins_per_side elif loc == "top_right": return pins_per_side * 2 + 1 return 0 def clockwise_dual(pincount, init=1, start="top_left", axis="x", **kwargs): """Generator for dual row packages counting clockwise. Args: pincount: Total number of pins init: Initial starting count (default: 1) start: The starting corner, top/bottom - left/right axis: Pin axis, either x or y. Is depended on num_pins_{x,y} **kwargs: Other keyword arguments Returns: Iterator """ i = _get_pin_cw(pincount, start) if axis == "y": pins = iter(range(pincount, 0, -1)) else: pins = iter(range(pincount)) for ind in pins: yield ((i + ind) % pincount) + init def counter_clockwise_dual(pincount, init=1, start="top_left", axis="x", **kwargs): """Generator for dual row packages counting counter clockwise. Args: pincount: Total number of pins init: Initial starting count (default: 1) start: The starting corner, top/bottom - left/right axis: Pin axis, either x or y. Is depended on num_pins_{x,y} **kwargs: Other keyword arguments Returns: Iterator """ i = _get_pin_ccw(pincount, start) if axis == "x": pins = iter(range(pincount, 0, -1)) else: pins = iter(range(pincount)) for ind in pins: yield ((i + ind) % pincount) + init # Add available generators to the dictionary generators = { "increment": increment, "cw_dual": clockwise_dual, "ccw_dual": counter_clockwise_dual, } def get_generator(device_params): """Returns a pad number iterator based on device_params and selected generator. Fallback to plain increment. Args: device_params: Device parameters dictionary Returns: Pad number iterator Raises: KeyError: If generator not available """ # Fallback to plain increment pincount = device_params["num_pins_x"] * 2 + device_params["num_pins_y"] * 2 pad_nums = device_params.get("pad_numbers") if not pad_nums: return generators["increment"](pincount, **device_params) init = pad_nums.get("init", 1) gen = generators.get(pad_nums.get("generator")) if not gen: gens = ", ".join(generators.keys()) pad_generator = pad_nums.get("generator") raise KeyError("{}: Use one of [{}]".format(pad_generator, gens)) iterator = gen(pincount, init, **pad_nums) return iterator ================================================ FILE: scripts/tools/quad_dual_pad_border.py ================================================ from __future__ import division import sys, os sys.path.append(os.path.join(sys.path[0],"..","..")) # load kicad_mod path from KicadModTree import * # NOQA from pad_number_generators import get_generator def add_dual_or_quad_pad_border(kicad_mod, configuration, pad_details, device_params): pad_shape_details = {} pad_shape_details['shape'] = Pad.SHAPE_ROUNDRECT pad_shape_details['radius_ratio'] = configuration.get('round_rect_radius_ratio', 0) if 'round_rect_max_radius' in configuration: pad_shape_details['maximum_radius'] = configuration['round_rect_max_radius'] if 'hidden_pins' in device_params: pad_shape_details['hidden_pins'] = device_params['hidden_pins'] if 'deleted_pins' in device_params: pad_shape_details['deleted_pins'] = device_params['deleted_pins'] if device_params['num_pins_x'] == 0: radius = add_dual_pad_border_y(kicad_mod, pad_details, device_params, pad_shape_details) elif device_params['num_pins_y'] == 0: radius = add_dual_pad_border_x(kicad_mod, pad_details, device_params, pad_shape_details) else: radius = add_quad_pad_border( kicad_mod, pad_details, device_params, pad_shape_details, configuration.get('kicad4_compatible', False)) return radius def add_dual_pad_border_y(kicad_mod, pad_details, device_params, pad_shape_details): init = 1 increment = get_generator(device_params) pa = PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=device_params['pitch'], increment=increment, **pad_details['left'], **pad_shape_details, ) kicad_mod.append(pa) init += device_params['num_pins_y'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=-device_params['pitch'], increment=increment, **pad_details['right'], **pad_shape_details, ) ) pads = pa.getVirtualChilds() pad = pads[0] return pad.getRoundRadius() def add_dual_pad_border_x(kicad_mod, pad_details, device_params, pad_shape_details): #for devices with clockwise numbering init = 1 increment = get_generator(device_params) pa = PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=device_params['pitch'], increment=increment, **pad_details['top'], **pad_shape_details, ) kicad_mod.append(pa) init += device_params['num_pins_x'] kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=-device_params['pitch'], increment=increment, **pad_details['bottom'], **pad_shape_details, ) ) pads = pa.getVirtualChilds() pad = pads[0] return pad.getRoundRadius() def add_quad_pad_border(kicad_mod, pad_details, device_params, pad_shape_details, kicad4_compatible): chamfer_size = device_params.get('chamfer_edge_pins', 0) pad_size_red = device_params.get('edge_heel_reduction', 0) if kicad4_compatible: chamfer_size = 0 pad_size_red += device_params.get('chamfer_edge_pins', 0) init = 1 corner_first = CornerSelection({CornerSelection.TOP_RIGHT: True}) corner_last = CornerSelection({CornerSelection.BOTTOM_RIGHT: True}) pad_size_reduction = {'x+': pad_size_red} if pad_size_red > 0 else None increment = get_generator(device_params) pa = PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, end_pads_size_reduction = pad_size_reduction, increment=increment, **pad_details['left'], **pad_shape_details, ) kicad_mod.append(pa) init += device_params['num_pins_y'] corner_first = copy(corner_first).rotateCCW() corner_last = copy(corner_last).rotateCCW() pad_size_reduction = {'y-': pad_size_red} if pad_size_red > 0 else None kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, end_pads_size_reduction = pad_size_reduction, increment=increment, **pad_details['bottom'], **pad_shape_details, ) ) init += device_params['num_pins_x'] corner_first = copy(corner_first).rotateCCW() corner_last = copy(corner_last).rotateCCW() pad_size_reduction = {'x-': pad_size_red} if pad_size_red > 0 else None kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_y'], x_spacing=0, y_spacing=-device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, end_pads_size_reduction = pad_size_reduction, increment=increment, **pad_details['right'], **pad_shape_details, ) ) init += device_params['num_pins_y'] corner_first = copy(corner_first).rotateCCW() corner_last = copy(corner_last).rotateCCW() pad_size_reduction = {'y+': pad_size_red} if pad_size_red > 0 else None kicad_mod.append(PadArray( initial= init, type=Pad.TYPE_SMT, layers=Pad.LAYERS_SMT, pincount=device_params['num_pins_x'], y_spacing=0, x_spacing=-device_params['pitch'], chamfer_size=chamfer_size, chamfer_corner_selection_first=corner_first, chamfer_corner_selection_last=corner_last, end_pads_size_reduction = pad_size_reduction, increment=increment, **pad_details['top'], **pad_shape_details, ) ) pads = pa.getVirtualChilds() pad = pads[0] return pad.getRoundRadius() ================================================ FILE: setup.py ================================================ #!/usr/bin/env python3 import os import sys from setuptools import setup from setuptools import find_packages long_description = open(os.path.join(sys.path[0], 'README.md')).read() setup( name='KicadModTree', version='1.1.2', author='Thomas Pointhuber', author_email='thomas.pointhuber@gmx.at', url='https://github.com/pointhi/kicad-footprint-generator', description="creating kicad footprints using python scripts", long_description=long_description, long_description_content_type='text/markdown', license="GPL3+", install_requires=[ 'future', 'pyyaml' ], extras_require={ 'test': [ 'pep8', 'flake8', 'unittest2', 'nose2', 'nose2-cov' ] }, packages=find_packages('.', exclude=["*tests*", "*examples*"]), test_suite='tests', classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', 'Programming Language :: Python', 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)' ], ) ================================================ FILE: tox.ini ================================================ [pep8] max-line-length = 120 [flake8] max-line-length = 120