diff --git a/ergogen/config.yaml b/ergogen/config.yaml index a9ffd11..cd0626d 100644 --- a/ergogen/config.yaml +++ b/ergogen/config.yaml @@ -29,6 +29,9 @@ units: $default_spread: cx $default_padding: cy + # Vertical offset between function keys and primary keys + function_zone_offset: 3 + # Define the points (i.e. keys) points: key: @@ -46,52 +49,112 @@ points: rows: # Modifier row (Ctrl, ..., but excluding the thumb keys) mods: + row_net: GP13 + led_previous_key: "{{zone.name}}_{{neighbor_col_left}}_{{row}}" + tags: [ is_key, flip_led ] + # Bottom letter row (Shift, ZXCV...) bottom: + row_net: GP14 + led_previous_key: "{{zone.name}}_{{neighbor_col_right}}_{{row}}" + # Middle/home letter row (Caps Lock, ASDFG...) home: + row_net: GP15 + led_previous_key: "{{zone.name}}_{{neighbor_col_left}}_{{row}}" + tags: [ is_key, flip_led ] + # Top letter row (Tab, QWERT...) top: + row_net: GP16 + led_previous_key: "{{zone.name}}_{{neighbor_col_right}}_{{row}}" + # Number row (`, 12345...) numbers: + row_net: GP17 + led_previous_key: "{{zone.name}}_{{neighbor_col_left}}_{{row}}" + tags: [ is_key, flip_led ] # Key columns (from left to right) columns: # Left-most column (`, Tab, Caps Lock, Shift, Ctrl) zero: + key.column_net: GP8 + key.neighbor_col_right: one + rows.numbers.led_previous_key: function_esc_default + rows.home.led_previous_key: primary_zero_top + rows.mods.led_previous_key: primary_zero_bottom # First letter column (1, Q) one: + key.column_net: GP7 + key.neighbor_col_left: zero + key.neighbor_col_right: two # Second letter column (2, W) two: + key.column_net: GP6 + key.neighbor_col_left: one + key.neighbor_col_right: three rows.mods.skip: true # Third letter column (3, E) three: + key.column_net: GP5 + key.neighbor_col_left: two + key.neighbor_col_right: four rows.mods.skip: true # Fourth letter column (4, R) four: + key.column_net: GP4 + key.neighbor_col_left: three + key.neighbor_col_right: five rows.mods.skip: true # Fifth letter column (5, T) five: + key.column_net: GP3 + key.neighbor_col_left: four + key.neighbor_col_right: six rows.mods.skip: true # Sixth letter column (6, Y) six: + key.column_net: GP2 + key.neighbor_col_left: five + key.neighbor_col_right: seven rows.mods.skip: true # Seventh letter column (7, U) seven: + key.column_net: GP1 + key.neighbor_col_left: six + key.neighbor_col_right: eight rows.mods.skip: true # Eighth letter column (8, I) eight: + key.column_net: GP0 + key.neighbor_col_left: seven + key.neighbor_col_right: nine rows.mods.skip: true # Nineth letter column (9, O) nine: + key.column_net: GP25 + key.neighbor_col_left: eight + key.neighbor_col_right: ten rows.mods.skip: true # Tenth letter column (0, P) ten: + key.column_net: GP24 + key.neighbor_col_left: nine + key.neighbor_col_right: eleven rows.mods.skip: true # Eleventh letter column (-, [) eleven: + key.column_net: GP23 + key.neighbor_col_left: ten + key.neighbor_col_right: twelve + rows.mods.led_previous_key: thumb_mirror_one_default # Twelfth letter column (=, ]) twelve: + key.column_net: GP22 + key.neighbor_col_left: eleven + rows.top.led_previous_key: primary_twelve_numbers + rows.bottom.led_previous_key: primary_twelve_home # Thumb fan thumb: @@ -102,54 +165,121 @@ points: # Rotate the thumb keys around the bottom-left corner of the key key: + row_net: GP13 + tags: [ is_key, flip_led ] origin: [ -0.5cx, -0.5cy ] splay: -4 # Define thumb keys columns: one: + key.column_net: GP6 + key.mirror.column_net: GP24 + key.led_previous_key: primary_one_mods + key.mirror.led_previous_key: thumb_mirror_two_default two: + key.column_net: GP5 + key.mirror.column_net: GP25 + key.led_previous_key: thumb_one_default + key.mirror.led_previous_key: thumb_mirror_three_default three: + key.column_net: GP4 + key.mirror.column_net: GP0 + key.led_previous_key: thumb_two_default + key.mirror.led_previous_key: thumb_mirror_four_default four: + key.column_net: GP3 + key.mirror.column_net: GP1 + key.led_previous_key: thumb_three_default + key.mirror.led_previous_key: thumb_four_default - # Mirror the board with a distance of 1 key between the upper corners + # Mirror the thumb fan mirror: ref: primary_five_numbers shift: [ 0.5cx, 0.5cx ] distance: 1cx - # Extra row above the primary zone (including rotary encoder) - extra: - # Position extra row above primary zone with 3mm of vertical offset + # Function key row above the primary zone (Esc + 8 more keys) + # (Note that the keys are only named "f[1-8]" for convenience and are not a full set of F1-F12 keys. They can be + # used as F-keys when needed, but will more likely be used for macros and other special functions.) + function: + # Position function key row above primary zone with 3mm of vertical offset anchor: ref: primary_zero_numbers - shift: [ 0, cy + 3 ] + shift: [ 0, cy + function_zone_offset ] - # Define extra keys - # (The "F" keys will likely be used for macros and other special functions, but can be mapped to specific F keys - # when needed.) + key: + row_net: GP12 + + # Define function keys columns: # Escape key esc: + key.column_net: GP8 + key.led_previous_key: function_f1_default - # Block of 4 extra keys with 6mm offset + # Block of 4 keys with 6mm offset f1: key.spread: cx + 6 + key.column_net: GP7 + key.led_previous_key: function_f2_default f2: + key.column_net: GP6 + key.led_previous_key: function_f3_default f3: + key.column_net: GP5 + key.led_previous_key: function_f4_default f4: + key.column_net: GP4 + key.led_previous_key: function_f5_default - # Block of 4 extra keys with 6mm offset + # Block of 4 keys with 6mm offset f5: key.spread: cx + 6 + key.column_net: GP3 + key.led_previous_key: function_f6_default f6: + key.column_net: GP2 + key.led_previous_key: function_f7_default f7: + key.column_net: GP1 + key.led_previous_key: function_f8_default f8: + key.column_net: GP0 + key.led_previous_key: status_led - # Rotary encoder in the upper right corner, with offset to be centered between columns eleven/twelve + # Additional points for special components in the upper right corner: Status LED, reset button, rotary encoder + special: + # Align points with the function key zone + anchor: + ref: primary_ten_numbers + shift: [ 0, cy + function_zone_offset ] + + # These are not actually keys + key: + tags: [ no_key ] + + # Define points + columns: + # Neopixel status LED (first in the chain, see comment in PCB footprints for details) + status_led: + key: + width: 3.4 + height: 3.0 + + # Reset button + reset_button: + key: + shift: [ -0.25cx - 1, 0 ] + width: 6.5 + height: 6.5 + + # Rotary encoder in the upper right corner rotary: key: - spread: 2.5cx + 7 + row_net: GP12 + column_net: GP22 + shift: [ -0.25cx, 0 ] width: 20.5 height: 20.5 tags: [ is_rotary_encoder ] @@ -176,9 +306,9 @@ outlines: - what: polygon points: - ref: primary_zero_numbers - shift: [ -0.5cx, 1.5cy + 3 ] + shift: [ -0.5cx, 1.5cy + function_zone_offset ] - ref: primary_twelve_numbers - shift: [ 0.5cx, 1.5cy + 3 ] + shift: [ 0.5cx, 1.5cy + function_zone_offset ] - ref: primary_twelve_mods shift: [ 0.5cx, -0.5cy ] - ref: mirror_thumb_four @@ -187,7 +317,7 @@ outlines: shift: [ 0.5cx, -0.5cy ] - ref: primary_zero_mods shift: [ -0.5cx, -0.5cy ] - expand: 4 + expand: 6 # Preview version of board with key caps and components for visualization board_preview: @@ -198,8 +328,18 @@ outlines: operation: stack where: primary_eleven_numbers size: [ 54, 20 ] - adjust.shift: [ 0, cy + 3 ] - # Rotary encoder (component) + adjust.shift: [ 0, cy + function_zone_offset ] + # Status LED + - what: rectangle + operation: stack + where: special_status_led + size: [ 3.4, 3.0 ] + # Reset button + - what: rectangle + operation: stack + where: special_reset_button + size: [ 6.5, 6.5 ] + # Rotary encoder - what: outline name: rotary_encoder operation: stack @@ -215,3 +355,143 @@ outlines: switch_plate: - board - -switch_cutouts + +# Generate the PCB +pcbs: + eepyboard: + outlines: + main: + outline: board + + footprints: + controller: + what: rp2040_purple + where: + ref: primary_eleven_numbers + shift: [ 0, cy + function_zone_offset ] + rotate: 90 + params: + orientation: down + # Use VBUS (5V from USB) as VCC net + VBUS: VCC + + choc_hotswap: + what: choc_pretty + where: is_key + # Rotate footprint so that the hotswap socket is at the bottom and the LED can be at the top + adjust.rotate: 180 + params: + keycaps: true + hotswap: true + from: "{{colrow}}" + to: "{{column_net}}" + + diode: + what: diode_smd + where: is_key + adjust: + shift: [ 7, -7 ] + rotate: 90 + resist: true + params: + side: B + from: "{{colrow}}" + to: "{{row_net}}" + + rotary_encoder: + what: rotary_modified + where: is_rotary_encoder + params: + from: "{{colrow}}" + to: "{{column_net}}" + A: GP10 + B: GP11 + C: GND + + diode_rotary_encoder: + $extends: pcbs.eepyboard.footprints.diode + where: is_rotary_encoder + adjust: + shift: [ 0, 0 ] + rotate: 0 + + led_chip: + what: sk6812_mini_e + # Place unrotated LEDs in all rows without the flip_led tag + where: [ [ is_key, -flip_led ] ] + # Position LEDs on the LED hole in the Choc switches + adjust: + shift: [ 0, 4.7 ] + params: + side: B + din: "led_dout_{{led_previous_key}}" + dout: "led_dout_{{zone.name}}_{{colrow}}" + + led_capacitor: + what: cap_0805 + where: [ [ is_key, -flip_led ] ] + adjust: + shift: [ -6, 4.5 ] + rotate: 90 + resist: true + params: + side: B + from: VCC + to: GND + + led_chip_flipped: + $extends: pcbs.eepyboard.footprints.led_chip + # Place flipped (rotated by 180°) LEDs in all rows *with* the flip_led tag + where: [ [ is_key, flip_led ] ] + adjust.rotate: 180 + + led_capacitor_flipped: + $extends: pcbs.eepyboard.footprints.led_capacitor + where: [ [ is_key, flip_led ] ] + adjust: + shift: [ 6, 4.9 ] + rotate: 270 + resist: true + + # Additional first LED (not bound to a key) that serves as a status LED. + # Additionally, it runs on a reduced voltage to serve as a level converter for the next LED: The RP2040 runs on + # 3.3V, but the SK6812 runs on 5V and requires at least 3.5V (5V * 0.7) for the control signal. By reducing the + # power voltage with a diode, the threshold is reduced as well, so that the signal of the RP2040 is strong enough. + status_led_chip: + what: sk6812_mini_e + where: special_status_led + params: + side: B + VCC: VCC_status_led + din: GP9 + dout: led_dout_status_led + + status_led_capacitor: + what: cap_0805 + where: special_status_led + adjust: + shift: [ -6, -0.2 ] + rotate: 90 + params: + side: B + from: VCC_status_led + to: GND + + # Diode to reduce the voltage of the first LED chip by ~0.7V + status_led_diode: + what: diode_smd + where: special_status_led + adjust: + shift: [ 0, 3.5 ] + rotate: 0 + params: + side: B + from: VCC + to: VCC_status_led + + reset_button: + what: button_6x6 + where: special_reset_button + params: + from: GND + to: RUN diff --git a/ergogen/footprints/button_6x6.js b/ergogen/footprints/button_6x6.js new file mode 100644 index 0000000..034877d --- /dev/null +++ b/ergogen/footprints/button_6x6.js @@ -0,0 +1,48 @@ +// Tactile button 6x6mm +// Source: https://kicad.github.io/footprints/Button_Switch_SMD +module.exports = { + params: { + designator: 'B', + side: 'F', + from: undefined, + to: undefined + }, + body: p => ` + (module SW_Push_1P1T_NO_6x6mm_H9.5mm (layer F.Cu) (tedit 5CA1CA7F) + (descr "tactile push button, 6x6mm e.g. PTS645xx series, height=9.5mm") + (tags "tact sw push 6mm smd") + (attr smd) + + ${p.at /* parametric position */} + + ${'' /* footprint reference */} + (fp_text reference "${p.ref}" (at 0 -4.05) (layer F.SilkS) ${p.ref_hide} (effects (font (size 1 1) (thickness 0.15)))) + (fp_text value "" (at 0 4.15) (layer F.SilkS) hide (effects (font (size 1 1) (thickness 0.15)))) + + ${'' /* outline */} + (fp_line (start -3 -3 ) (end -3 3 ) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start -3 3 ) (end 3 3 ) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start 3 3 ) (end 3 -3 ) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start 3 -3 ) (end -3 -3 ) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start 5 3.25) (end 5 -3.25) (layer ${p.side}.CrtYd) (width 0.05)) + (fp_line (start -5 -3.25) (end -5 3.25) (layer ${p.side}.CrtYd) (width 0.05)) + (fp_line (start -5 3.25) (end 5 3.25) (layer ${p.side}.CrtYd) (width 0.05)) + (fp_line (start -5 -3.25) (end 5 -3.25) (layer ${p.side}.CrtYd) (width 0.05)) + (fp_line (start 3.23 -3.23) (end 3.23 -3.2 ) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start 3.23 3.23) (end 3.23 3.2 ) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start -3.23 3.23) (end -3.23 3.2 ) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start -3.23 -3.2 ) (end -3.23 -3.23) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start 3.23 -1.3 ) (end 3.23 1.3 ) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start -3.23 -3.23) (end 3.23 -3.23) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start -3.23 -1.3 ) (end -3.23 1.3 ) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start -3.23 3.23) (end 3.23 3.23) (layer ${p.side}.SilkS) (width 0.12)) + (fp_circle (center 0 0) (end 1.75 -0.05) (layer ${p.side}.Fab) (width 0.1)) + + ${'' /* pins */} + (pad 1 smd rect (at -3.975 -2.25 ${p.r}) (size 1.55 1.3) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from}) + (pad 1 smd rect (at 3.975 -2.25 ${p.r}) (size 1.55 1.3) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from}) + (pad 2 smd rect (at -3.975 2.25 ${p.r}) (size 1.55 1.3) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to}) + (pad 2 smd rect (at 3.975 2.25 ${p.r}) (size 1.55 1.3) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to}) + ) + ` +} diff --git a/ergogen/footprints/cap_0805.js b/ergogen/footprints/cap_0805.js new file mode 100644 index 0000000..7dc467a --- /dev/null +++ b/ergogen/footprints/cap_0805.js @@ -0,0 +1,37 @@ +module.exports = { + params: { + designator: 'C', + side: 'F', + from: undefined, + to: undefined + }, + body: p => ` + (module C_0805_2012Metric (layer ${p.side}.Cu) (tedit 5F68FEEE) + ${p.at /* parametric position */} + + ${'' /* footprint reference */} + (fp_text reference "${p.ref}" (at 0 0) (layer ${p.side}.SilkS) ${p.ref_hide} (effects (font (size 1.27 1.27) (thickness 0.15)))) + (fp_text value "" (at 0 0) (layer ${p.side}.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15)))) + + ${''/* capacitor symbols */} + (fp_line (start -1 0.625) (end -1 -0.625) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start -1 -0.625) (end 1 -0.625) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start 1 -0.625) (end 1 0.625) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start 1 0.625) (end -1 0.625) (layer ${p.side}.Fab) (width 0.1)) + (fp_line (start -0.261252 -0.735) (end 0.261252 -0.735) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start -0.261252 0.735) (end 0.261252 0.735) (layer ${p.side}.SilkS) (width 0.12)) + (fp_line (start -1.7 0.98) (end -1.7 -0.98) (layer ${p.side}.CrtYd) (width 0.05)) + (fp_line (start -1.7 -0.98) (end 1.7 -0.98) (layer ${p.side}.CrtYd) (width 0.05)) + (fp_line (start 1.7 -0.98) (end 1.7 0.98) (layer ${p.side}.CrtYd) (width 0.05)) + (fp_line (start 1.7 0.98) (end -1.7 0.98) (layer ${p.side}.CrtYd) (width 0.05)) + + ${''/* SMD pads */} + (pad 1 smd roundrect (at -0.95 0 ${p.r}) (size 1 1.45) (layers ${p.side}.Cu ${p.side}.Mask ${p.side}.Paste) + (roundrect_rratio 0.25) ${p.to} + ) + (pad 2 smd roundrect (at 0.95 0 ${p.r}) (size 1 1.45) (layers ${p.side}.Cu ${p.side}.Mask ${p.side}.Paste) + (roundrect_rratio 0.25) ${p.from} + ) + ) + ` +} diff --git a/ergogen/footprints/choc_pretty.js b/ergogen/footprints/choc_pretty.js new file mode 100644 index 0000000..7d56155 --- /dev/null +++ b/ergogen/footprints/choc_pretty.js @@ -0,0 +1,149 @@ +// Modified version of choc.js +// Source for modifications: https://github.com/daprice/keyswitches.pretty/blob/master/Kailh_socket_PG1350.kicad_mod +// --------------------------- +// Kailh Choc PG1350 +// Nets +// from: corresponds to pin 1 +// to: corresponds to pin 2 +// Params +// hotswap: default is false +// if true, will include holes and pads for Kailh choc hotswap sockets +// reverse: default is false +// if true, will flip the footprint such that the pcb can be reversible +// keycaps: default is false +// if true, will add choc sized keycap box around the footprint +// +// note: hotswap and reverse can be used simultaneously + +module.exports = { + params: { + designator: 'S', + hotswap: false, + reverse: false, + keycaps: false, + from: undefined, + to: undefined, + }, + body: p => { + const standard = ` + (module PG1350 (layer F.Cu) (tedit 5DD50112) + ${p.at /* parametric position */} + + ${'' /* footprint reference */} + (fp_text reference "${p.ref}" (at 0 0) (layer F.SilkS) ${p.ref_hide} (effects (font (size 1.27 1.27) (thickness 0.15)))) + (fp_text value "" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15)))) + + ${'' /* LED hole marks */} + (fp_line (start -2.6 3.1) (end 2.6 3.1) (layer Dwgs.User) (width 0.15)) + (fp_line (start 2.6 3.1) (end 2.6 6.3) (layer Dwgs.User) (width 0.15)) + (fp_line (start 2.6 6.3) (end -2.6 6.3) (layer Dwgs.User) (width 0.15)) + (fp_line (start -2.6 3.1) (end -2.6 6.3) (layer Dwgs.User) (width 0.15)) + + ${'' /* middle shaft */} + (pad "" np_thru_hole circle (at 0 0) (size 3.429 3.429) (drill 3.429) (layers *.Cu *.Mask)) + + ${'' /* stabilizers */} + (pad "" np_thru_hole circle (at 5.5 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask)) + (pad "" np_thru_hole circle (at -5.5 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask)) + `; + + const keycap = ` + ${'' /* keycap marks */} + (fp_line (start -9 -8.5) (end 9 -8.5) (layer Dwgs.User) (width 0.15)) + (fp_line (start 9 -8.5) (end 9 8.5) (layer Dwgs.User) (width 0.15)) + (fp_line (start 9 8.5) (end -9 8.5) (layer Dwgs.User) (width 0.15)) + (fp_line (start -9 8.5) (end -9 -8.5) (layer Dwgs.User) (width 0.15)) + `; + + function switch_marks(reversed) { + let def_side = reversed ? 'F' : 'B'; + + return ` + ${'' /* switch marks */} + (fp_line (start -7 -7) (end 7 -7) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start 7 -7) (end 7 7) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start 7 7) (end -7 7) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start -7 7) (end -7 -7) (layer ${def_side}.SilkS) (width 0.15)) + `; + } + + function pins(reversed) { + let def_neg = reversed ? '' : '-'; + let def_pos = reversed ? '-' : ''; + let def_side = reversed ? 'F' : 'B'; + let def_pin1 = reversed ? p.to : p.from; + let def_pin2 = reversed ? p.from : p.to; + + if (p.hotswap) { + return ` + ${'' /* hotswap socket marks */} + (fp_line (start ${def_pos}7 -5.6) (end ${def_pos}7 -6.2) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_neg}1.5 -3.7) (end ${def_pos}1 -3.7) (layer ${def_side}.SilkS) (width 0.15)) + (fp_arc (start ${def_pos}1 -2.2) (end ${def_pos}2.5 -2.2) (angle ${def_neg}90) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_pos}1.5 -8.2) (end ${def_pos}2 -7.7) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_pos}2 -6.7) (end ${def_pos}2 -7.7) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_pos}7 -6.2) (end ${def_pos}2.5 -6.2) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_neg}2 -4.2) (end ${def_neg}1.5 -3.7) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_neg}2 -7.7) (end ${def_neg}1.5 -8.2) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_neg}1.5 -8.2) (end ${def_pos}1.5 -8.2) (layer ${def_side}.SilkS) (width 0.15)) + (fp_arc (start ${def_pos}2.5 -6.7) (end ${def_pos}2 -6.7) (angle ${def_neg}90) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_pos}2.5 -2.2) (end ${def_pos}2.5 -1.5) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_pos}2.5 -1.5) (end ${def_pos}7 -1.5) (layer ${def_side}.SilkS) (width 0.15)) + (fp_line (start ${def_pos}7 -1.5) (end ${def_pos}7 -2 ) (layer ${def_side}.SilkS) (width 0.15)) + + (fp_arc (start ${def_pos}2.5 -6.7 ) (end ${def_pos}2 -6.7 ) (angle ${def_neg}90) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_neg}1.5 -8.2 ) (end ${def_pos}1.5 -8.2 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_neg}2 -7.7 ) (end ${def_neg}1.5 -8.2 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_neg}1.5 -3.7 ) (end ${def_pos}1 -3.7 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_neg}2 -4.2 ) (end ${def_neg}1.5 -3.7 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_pos}7 -6.2 ) (end ${def_pos}2.5 -6.2 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_pos}2 -6.7 ) (end ${def_pos}2 -7.7 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_pos}1.5 -8.2 ) (end ${def_pos}2 -7.7 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_arc (start ${def_pos}1 -2.2 ) (end ${def_pos}2.5 -2.2 ) (angle ${def_neg}90) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_pos}2.5 -1.5 ) (end ${def_pos}7 -1.5 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_pos}2.5 -2.2 ) (end ${def_pos}2.5 -1.5 ) (layer ${def_side}.Fab) (width 0.15)) + (fp_line (start ${def_neg}2 -4.25) (end ${def_neg}2 -7.7 ) (layer ${def_side}.Fab) (width 0.12)) + (fp_line (start ${def_pos}7 -1.5 ) (end ${def_pos}7 -6.2 ) (layer ${def_side}.Fab) (width 0.12)) + (fp_line (start ${def_pos}7 -5 ) (end ${def_pos}9.5 -5 ) (layer ${def_side}.Fab) (width 0.12)) + (fp_line (start ${def_pos}9.5 -5 ) (end ${def_pos}9.5 -2.5 ) (layer ${def_side}.Fab) (width 0.12)) + (fp_line (start ${def_pos}9.5 -2.5 ) (end ${def_pos}7 -2.5 ) (layer ${def_side}.Fab) (width 0.12)) + (fp_line (start ${def_neg}2 -4.75) (end ${def_neg}4.5 -4.75) (layer ${def_side}.Fab) (width 0.12)) + (fp_line (start ${def_neg}4.5 -4.75) (end ${def_neg}4.5 -7.25) (layer ${def_side}.Fab) (width 0.12)) + (fp_line (start ${def_neg}4.5 -7.25) (end ${def_neg}2 -7.25) (layer ${def_side}.Fab) (width 0.12)) + + ${'' /* holes */} + (pad "" np_thru_hole circle (at ${def_pos}5 -3.75) (size 3 3) (drill 3) (layers *.Cu *.Mask)) + (pad "" np_thru_hole circle (at 0 -5.95) (size 3 3) (drill 3) (layers *.Cu *.Mask)) + + ${'' /* net pads */} + (pad 1 smd rect (at ${def_neg}3.275 -5.95 ${p.r}) (size 2.6 2.6) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${def_pin1}) + (pad 2 smd rect (at ${def_pos}8.275 -3.75 ${p.r}) (size 2.6 2.6) (layers ${def_side}.Cu ${def_side}.Paste ${def_side}.Mask) ${def_pin2}) + `; + } else { + return ` + ${'' /* pins */} + (pad 1 thru_hole circle (at ${def_pos}5 -3.8) (size 2.032 2.032) (drill 1.27) (layers *.Cu *.Mask) ${def_pin1}) + (pad 2 thru_hole circle (at ${def_pos}0 -5.9) (size 2.032 2.032) (drill 1.27) (layers *.Cu *.Mask) ${def_pin2}) + `; + } + } + + if (p.reverse) { + return ` + ${standard} + ${p.keycaps ? keycap : ''} + ${switch_marks(false)} + ${switch_marks(true)} + ${pins(false)} + ${pins(true)} + )`; + } else { + return ` + ${standard} + ${p.keycaps ? keycap : ''} + ${switch_marks(false)} + ${pins(false)} + )`; + } + } +} diff --git a/ergogen/footprints/diode_smd.js b/ergogen/footprints/diode_smd.js new file mode 100644 index 0000000..f24d43e --- /dev/null +++ b/ergogen/footprints/diode_smd.js @@ -0,0 +1,30 @@ +module.exports = { + params: { + designator: 'D', + side: 'F', + from: undefined, + to: undefined + }, + body: p => ` + (module SmdDiode (layer ${p.side}.Cu) (tedit 65D012FE) + ${p.at /* parametric position */} + + ${'' /* footprint reference */} + (fp_text reference "${p.ref}" (at 0 0) (layer ${p.side}.SilkS) ${p.ref_hide} (effects (font (size 1.27 1.27) (thickness 0.15)))) + (fp_text value "" (at 0 0) (layer ${p.side}.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15)))) + + ${''/* diode symbols */} + (fp_line (start 0.25 0) (end 0.75 0) (layer ${p.side}.SilkS) (width 0.1)) + (fp_line (start 0.25 0.4) (end -0.35 0) (layer ${p.side}.SilkS) (width 0.1)) + (fp_line (start 0.25 -0.4) (end 0.25 0.4) (layer ${p.side}.SilkS) (width 0.1)) + (fp_line (start -0.35 0) (end 0.25 -0.4) (layer ${p.side}.SilkS) (width 0.1)) + (fp_line (start -0.35 0) (end -0.35 0.55) (layer ${p.side}.SilkS) (width 0.1)) + (fp_line (start -0.35 0) (end -0.35 -0.55) (layer ${p.side}.SilkS) (width 0.1)) + (fp_line (start -0.75 0) (end -0.35 0) (layer ${p.side}.SilkS) (width 0.1)) + + ${''/* SMD pads */} + (pad 1 smd rect (at -1.65 0 ${p.r}) (size 0.9 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.to}) + (pad 2 smd rect (at 1.65 0 ${p.r}) (size 0.9 1.2) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.from}) + ) + ` +} diff --git a/ergogen/footprints/rotary_modified.js b/ergogen/footprints/rotary_modified.js new file mode 100644 index 0000000..044baa1 --- /dev/null +++ b/ergogen/footprints/rotary_modified.js @@ -0,0 +1,68 @@ +// Modified version of rotary.js, without the mounting legs +// -------------------------------------------------------- +// EC12 rotary encoder +// Nets +// from: corresponds to switch pin 1 (for button presses) +// to: corresponds to switch pin 2 (for button presses) +// A: corresponds to pin 1 (for rotary) +// B: corresponds to pin 3 (for rotary) +// C: corresponds to pin 2 (for rotary, should be GND) + +module.exports = { + params: { + designator: 'ROT', + from: undefined, + to: undefined, + A: undefined, + B: undefined, + C: undefined, + radius: 10, + }, + body: p => ` + (module rotary_encoder (layer F.Cu) (tedit 603326DE) + + ${p.at /* parametric position */} + + ${'' /* footprint reference */} + (fp_text reference "${p.ref}" (at 0 0.5) (layer F.SilkS) + ${p.ref_hide} (effects (font (size 1 1) (thickness 0.15)))) + (fp_text value "" (at 0 8.89) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15)))) + + ${''/* component outline */} + (fp_line (start -0.62 -0.04) (end 0.38 -0.04) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.12 -0.54) (end -0.12 0.46) (layer F.SilkS) (width 0.12)) + (fp_line (start 5.98 3.26) (end 5.98 5.86) (layer F.SilkS) (width 0.12)) + (fp_line (start 5.98 -1.34) (end 5.98 1.26) (layer F.SilkS) (width 0.12)) + (fp_line (start 5.98 -5.94) (end 5.98 -3.34) (layer F.SilkS) (width 0.12)) + (fp_line (start -3.12 -0.04) (end 2.88 -0.04) (layer F.Fab) (width 0.12)) + (fp_line (start -0.12 -3.04) (end -0.12 2.96) (layer F.Fab) (width 0.12)) + (fp_line (start -7.32 -4.14) (end -7.62 -3.84) (layer F.SilkS) (width 0.12)) + (fp_line (start -7.92 -4.14) (end -7.32 -4.14) (layer F.SilkS) (width 0.12)) + (fp_line (start -7.62 -3.84) (end -7.92 -4.14) (layer F.SilkS) (width 0.12)) + (fp_line (start -6.22 -5.84) (end -6.22 5.86) (layer F.SilkS) (width 0.12)) + (fp_line (start -2.12 -5.84) (end -6.22 -5.84) (layer F.SilkS) (width 0.12)) + (fp_line (start -2.12 5.86) (end -6.22 5.86) (layer F.SilkS) (width 0.12)) + (fp_line (start 5.98 5.86) (end 1.88 5.86) (layer F.SilkS) (width 0.12)) + (fp_line (start 1.88 -5.94) (end 5.98 -5.94) (layer F.SilkS) (width 0.12)) + (fp_line (start -6.12 -4.74) (end -5.12 -5.84) (layer F.Fab) (width 0.12)) + (fp_line (start -6.12 5.76) (end -6.12 -4.74) (layer F.Fab) (width 0.12)) + (fp_line (start 5.88 5.76) (end -6.12 5.76) (layer F.Fab) (width 0.12)) + (fp_line (start 5.88 -5.84) (end 5.88 5.76) (layer F.Fab) (width 0.12)) + (fp_line (start -5.12 -5.84) (end 5.88 -5.84) (layer F.Fab) (width 0.12)) + (fp_line (start -8.87 -6.89) (end 7.88 -6.89) (layer F.CrtYd) (width 0.05)) + (fp_line (start -8.87 -6.89) (end -8.87 6.81) (layer F.CrtYd) (width 0.05)) + (fp_line (start 7.88 6.81) (end 7.88 -6.89) (layer F.CrtYd) (width 0.05)) + (fp_line (start 7.88 6.81) (end -8.87 6.81) (layer F.CrtYd) (width 0.05)) + (fp_circle (center -0.12 -0.04) (end 2.88 -0.04) (layer F.SilkS) (width 0.12)) + (fp_circle (center -0.12 -0.04) (end 2.88 -0.04) (layer F.Fab) (width 0.12)) + + ${''/* pin names */} + (pad A thru_hole rect (at -7.62 -2.54 ${p.r}) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.A}) + (pad C thru_hole circle (at -7.62 -0.04) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.C}) + (pad B thru_hole circle (at -7.62 2.46) (size 2 2) (drill 1) (layers *.Cu *.Mask) ${p.B}) + (pad 1 thru_hole circle (at 6.88 -2.54) (size 1.5 1.5) (drill 1) (layers *.Cu *.Mask) ${p.from}) + (pad 2 thru_hole circle (at 6.88 2.46) (size 1.5 1.5) (drill 1) (layers *.Cu *.Mask) ${p.to}) + ) + ` +} diff --git a/ergogen/footprints/rp2040_purple.js b/ergogen/footprints/rp2040_purple.js new file mode 100644 index 0000000..7ff0f1f --- /dev/null +++ b/ergogen/footprints/rp2040_purple.js @@ -0,0 +1,140 @@ +// Pin header footprint for a RP2040-based controller board from AliExpress. +// Doesn't really have a name, it's just "the purple one with USB-C". +// The pinout differs from the Raspberry Pi Pico! +// ------------------------------- +// Params +// orientation: if up (default), the controller will be on the front side of the PCB, otherwise on the back side + +module.exports = { + params: { + designator: 'MCU', + orientation: 'up', + + // Right side of pins (with USB port at the top), top to bottom + VBUS: {type: 'net', value: 'VBUS'}, + VIN: {type: 'net', value: 'VIN'}, + GND: {type: 'net', value: 'GND'}, + '3V3_EN': {type: 'net', value: '3V3_EN'}, + '3V3': {type: 'net', value: '3V3'}, + // (GND pin) + RUN: {type: 'net', value: 'RUN'}, // Reset pin: Pull down to reset + GP29: {type: 'net', value: 'GP29'}, // also: ADC3 + GP28: {type: 'net', value: 'GP28'}, // also: ADC2 + GP27: {type: 'net', value: 'GP27'}, // also: ADC1 + GP26: {type: 'net', value: 'GP26'}, // also: ADC0 + AGND: {type: 'net', value: 'AGND'}, + GP25: {type: 'net', value: 'GP25'}, + GP24: {type: 'net', value: 'GP24'}, + GP23: {type: 'net', value: 'GP23'}, + GP22: {type: 'net', value: 'GP22'}, + GP21: {type: 'net', value: 'GP21'}, + GP20: {type: 'net', value: 'GP20'}, + GP19: {type: 'net', value: 'GP19'}, + GP18: {type: 'net', value: 'GP18'}, + + // Left side of pins (with USB port at the top), top to bottom + GP0: {type: 'net', value: 'GP0'}, + GP1: {type: 'net', value: 'GP1'}, + GP2: {type: 'net', value: 'GP2'}, + GP3: {type: 'net', value: 'GP3'}, + GP4: {type: 'net', value: 'GP4'}, + // (GND pin) + GP5: {type: 'net', value: 'GP5'}, + GP6: {type: 'net', value: 'GP6'}, + GP7: {type: 'net', value: 'GP7'}, + GP8: {type: 'net', value: 'GP8'}, + GP9: {type: 'net', value: 'GP9'}, + GP10: {type: 'net', value: 'GP10'}, + GP11: {type: 'net', value: 'GP11'}, + GP12: {type: 'net', value: 'GP12'}, + // (GND pin) + GP13: {type: 'net', value: 'GP13'}, + GP14: {type: 'net', value: 'GP14'}, + GP15: {type: 'net', value: 'GP15'}, + GP16: {type: 'net', value: 'GP16'}, + GP17: {type: 'net', value: 'GP17'}, + }, + body: p => { + let def_neg, def_pos, side, mirror; + if (p.orientation === 'down') { + def_neg = ''; + def_pos = '-'; + side = 'B'; + mirror = 'mirror'; + } else { + def_neg = '-'; + def_pos = ''; + side = 'F'; + mirror = ''; + } + + const PINS_PER_SIDE = 20; + const PINS_PER_SIDE_HALF = 10; + + const pins_left = [ + 'GP0', 'GP1', 'GP2', 'GP3', 'GP4', 'GND', 'GP5', 'GP6', 'GP7', 'GP8', + 'GP9', 'GP10', 'GP11', 'GP12', 'GND', 'GP13', 'GP14', 'GP15', 'GP16', 'GP17', + ]; + const pins_right = [ + 'VBUS', 'VIN', 'GND', '3V3_EN', '3V3', 'GND', 'RUN', 'GP29', 'GP28', 'GP27', + 'GP26', 'AGND', 'GP25', 'GP24', 'GP23', 'GP22', 'GP21', 'GP20', 'GP19', 'GP18', + ]; + + function pin_pos_y(pin_number) { + // Fucking floating points... + return (254 * (pin_number - PINS_PER_SIDE_HALF) + 127) / 100; + } + + function pin_labels(pin_names, right_side) { + const sign = right_side ? def_pos : def_neg; + const justify = right_side ? 'right' : 'left'; + let pin_label_body = ''; + + for (let i = 0; i < PINS_PER_SIDE; i++) { + pin_label_body += ` + (fp_text user ${pin_names[i]} (at ${sign}7.62 ${pin_pos_y(i)} ${p.r}) (unlocked yes) (layer ${side}.SilkS) + (effects (font (size 0.8 0.8) (thickness 0.15)) (justify ${justify} ${mirror})) + )`; + } + return pin_label_body; + } + + function pin_pads(pin_names, right_side) { + const sign = right_side ? def_pos : def_neg; + const offset = right_side ? 21 : 1; + let pin_pad_body = ''; + + for (let i = 0; i < PINS_PER_SIDE; i++) { + pin_pad_body += ` + (pad ${i + offset} thru_hole circle (at ${sign}8.89 ${pin_pos_y(i)} 0) + (size 1.7526 1.7526) (drill 1.0922) (layers *.Cu *.SilkS *.Mask) ${p[pin_names[i]]} + )`; + } + return pin_pad_body; + } + + return ` + (module RP2040_USB_C_Purple (layer F.Cu) (tedit 66A6C4CD) + ${p.at /* parametric position */} + + ${'' /* footprint reference */} + (fp_text reference "${p.ref}" (at 0 0) (layer ${side}.SilkS) ${p.ref_hide} (effects (font (size 1.27 1.27) (thickness 0.15)))) + (fp_text value "" (at 0 0) (layer ${side}.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15)))) + + ${'' /* component outline */} + (fp_line (start -10.16 -28.6) (end 10.16 -28.6) (layer ${side}.SilkS) (width 0.15)) + (fp_line (start 10.16 -28.6) (end 10.16 25.4) (layer ${side}.SilkS) (width 0.15)) + (fp_line (start 10.16 25.4) (end -10.16 25.4) (layer ${side}.SilkS) (width 0.15)) + (fp_line (start -10.16 25.4) (end -10.16 -28.6) (layer ${side}.SilkS) (width 0.15)) + + ${'' /* pin labels */} + ${pin_labels(pins_left, false)} + ${pin_labels(pins_right, true)} + + ${'' /* pin pads */} + ${pin_pads(pins_left, false)} + ${pin_pads(pins_right, true)} + ) + `; + } +} diff --git a/ergogen/footprints/sk6812_mini_e.js b/ergogen/footprints/sk6812_mini_e.js new file mode 100644 index 0000000..cdaf000 --- /dev/null +++ b/ergogen/footprints/sk6812_mini_e.js @@ -0,0 +1,52 @@ +// Modified version of rgb.js +// Source for KiCad footprint: https://github.com/keebio/Keebio-Parts.pretty/blob/master/SK6812-MINI-E.kicad_mod + +module.exports = { + params: { + designator: 'LED', + side: 'F', + din: undefined, + dout: undefined, + VCC: {type: 'net', value: 'VCC'}, + GND: {type: 'net', value: 'GND'} + }, + body: p => ` + (module SK6812-MINI-E (layer F.Cu) (tedit 53BEE615) + ${p.at /* parametric position */} + + ${'' /* footprint reference */} + (fp_text reference "${p.ref}" (at 0 0) (layer ${p.side}.SilkS) ${p.ref_hide} + (effects (font (size 1.27 1.27) (thickness 0.15))) + ) + (fp_text value "" (at 0 0) (layer ${p.side}.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15)))) + + (fp_poly (pts (xy 2.8 1.4) (xy 2.2 1.4) (xy 2.2 2)) (layer ${p.side}.SilkS) (width 0.1)) + (fp_line (start 1.6 -1.4) (end 1.6 1.4) (layer Cmts.User) (width 0.12)) + (fp_line (start 1.6 1.4) (end -1.6 1.4) (layer Cmts.User) (width 0.12)) + (fp_line (start -1.6 1.4) (end -1.6 -1.4) (layer Cmts.User) (width 0.12)) + (fp_line (start -1.6 -1.4) (end 1.6 -1.4) (layer Cmts.User) (width 0.12)) + (fp_line (start 1.7 -1.5) (end 1.7 1.5) (layer Edge.Cuts) (width 0.12)) + (fp_line (start 1.7 1.5) (end -1.7 1.5) (layer Edge.Cuts) (width 0.12)) + (fp_line (start -1.7 1.5) (end -1.7 -1.5) (layer Edge.Cuts) (width 0.12)) + (fp_line (start -1.7 -1.5) (end 1.7 -1.5) (layer Edge.Cuts) (width 0.12)) + + (pad "1" smd rect (at -2.55 -0.75 ${p.r}) (size 1.7 0.82) + (layers "${p.side}.Cu" "${p.side}.Paste" "${p.side}.Mask") + ${p.VCC} + ) + (pad "2" smd rect (at -2.55 0.75 ${p.r}) (size 1.7 0.82) + (layers "${p.side}.Cu" "${p.side}.Paste" "${p.side}.Mask") + ${p.dout} + ) + (pad "4" smd rect (at 2.55 -0.75 ${p.r}) (size 1.7 0.82) + (layers "${p.side}.Cu" "${p.side}.Paste" "${p.side}.Mask") + ${p.din} + ) + (pad "3" smd roundrect (at 2.55 0.75 ${p.r}) (size 1.7 0.82) + (layers "${p.side}.Cu" "${p.side}.Paste" "${p.side}.Mask") + (roundrect_rratio 0.25) + ${p.GND} + ) + ) + ` +}