# Ergogen config for the eepyBoard # # Reference information: # - Keycap size (FK MBK keycaps): 17.5mm x 16.5mm # Metadata meta: # Required version of Ergogen engine: "4.1.0" # Version of the board version: "1.1" author: binaryDiv # Define units and default values used throughout this file units: # Redefine choc units (keycap size + 1.5mm clearance) cx: 19 cy: 18 # Size of keycaps kcx: 17.5 kcy: 16.5 # Size of key rectangle in demo view (keycap size) $default_width: 17.5 $default_height: 16.5 # Actual spacing of keys $default_spread: cx $default_padding: cy # Vertical offset between function key row and main zone function_offset: 3 # Horizontal offset/gap between function key groups (Esc, F1-F4, F5-F8, F9-F12) function_gap: 6 # Distance between left and right half of the main zone split_gap_width: 2cx + 3 # Radius of rotary encoder knob (just for visualization) rotary_encoder_radius: 10 # Define the points (primarily the keys, but also some auxiliary points for # placement of other components, e.g. rotary encoders and the controller board) points: key: # Tag all points as "is_key" unless overwritten tags: [ is_key ] # Use 5V as VCC for all RGB LEDs, except for the first one in the chain led_vcc_net: VCC zones: # Main keyboard zone main: # Set anchor to fix placement on KiCad sheet anchor: shift: [ 75, -175 ] # Key rows (from bottom to top) rows: # Modifier row (Ctrl etc., but excluding the thumb keys) mods: row_net: ROW1 led_next_key: "{{zone.name}}_{{neighbor_col_left}}_{{row}}" # Bottom letter row bottom: row_net: ROW2 led_next_key: "{{zone.name}}_{{neighbor_col_right}}_{{row}}" tags: [ is_key, flip_led ] # Home letter row home: row_net: ROW3 led_next_key: "{{zone.name}}_{{neighbor_col_left}}_{{row}}" # Top letter row top: row_net: ROW4 led_next_key: "{{zone.name}}_{{neighbor_col_right}}_{{row}}" tags: [ is_key, flip_led ] # Number row numbers: row_net: ROW5 led_next_key: "{{zone.name}}_{{neighbor_col_left}}_{{row}}" # Key columns (from left to right) columns: # Left-most column (extra keys) left: key.column_net: COL1 key.neighbor_col_right: zero rows.numbers.led_next_key: main_left_top rows.home.led_next_key: main_left_bottom # Use placeholder to mark end of the RGB LED chain (unused net name) rows.mods.led_next_key: END_OF_CHAIN # Modifier column (`, Tab, Shift, etc.) zero: key.stagger: 1/8cy key.column_net: COL2 key.neighbor_col_left: left key.neighbor_col_right: one # First letter column (1, Q) one: key.stagger: 1/8cy key.column_net: COL3 key.neighbor_col_left: zero key.neighbor_col_right: two # Second letter column (2, W) two: key.stagger: 1/8cy key.column_net: COL4 key.neighbor_col_left: one key.neighbor_col_right: three rows.mods.skip: true # Third letter column (3, E) three: key.column_net: COL5 key.neighbor_col_left: two key.neighbor_col_right: four rows.mods.skip: true # Fourth letter column (4, R) four: key.stagger: -(1/4cy) key.column_net: COL6 key.neighbor_col_left: three key.neighbor_col_right: five rows.mods.skip: true # Fifth letter column (5, T) five: key.stagger: -(1/4cy) key.column_net: COL7 key.neighbor_col_left: four key.neighbor_col_right: six rows.top.led_next_key: arrow_keys_up rows.bottom.led_next_key: arrow_keys_down rows.mods.skip: true # (Gap with arrow keys in the middle: Matrix column 8) # Sixth letter column (6, Y) six: key.spread: cx + split_gap_width key.column_net: COL9 key.neighbor_col_left: five key.neighbor_col_right: seven rows.home.led_next_key: arrow_keys_right rows.mods.skip: true # Seventh letter column (7, U) seven: key.stagger: 1/4cy key.column_net: COL10 key.neighbor_col_left: six key.neighbor_col_right: eight rows.mods.skip: true # Eighth letter column (8, I) eight: key.stagger: 1/4cy key.column_net: COL11 key.neighbor_col_left: seven key.neighbor_col_right: nine rows.mods.skip: true # Nineth letter column (9, O) nine: key.column_net: COL12 key.neighbor_col_left: eight key.neighbor_col_right: ten rows.mods.skip: true # Tenth letter column (0, P) ten: key.stagger: -(1/8cy) key.column_net: COL13 key.neighbor_col_left: nine key.neighbor_col_right: eleven rows.mods.led_next_key: mirror_thumb_one # Eleventh letter column (-, [) eleven: key.stagger: -(1/8cy) key.column_net: COL14 key.neighbor_col_left: ten key.neighbor_col_right: twelve # Twelfth letter column (=, ]) twelve: key.stagger: -(1/8cy) key.column_net: COL15 key.neighbor_col_left: eleven rows.top.led_next_key: main_twelve_home rows.bottom.led_next_key: main_twelve_mods # Thumb fan thumb: # Position thumb keys based on the third key in the modifier row anchor: ref: main_one_mods shift: [ cx + 1, 0 ] # Zone-wide key settings key: row_net: ROW1 # Rotate the thumb keys around the bottom-left corner of the key origin: [ -0.5cx, -0.5cy ] splay: -6 # Define thumb keys columns: one: key.column_net: COL4 key.mirror.column_net: COL12 key.led_next_key: main_one_mods key.mirror.led_next_key: mirror_thumb_two two: key.column_net: COL5 key.mirror.column_net: COL11 key.led_next_key: thumb_one key.mirror.led_next_key: mirror_thumb_three three: key.column_net: COL6 key.mirror.column_net: COL10 key.led_next_key: thumb_two key.mirror.led_next_key: mirror_thumb_four four: key.column_net: COL7 key.mirror.column_net: COL9 key.led_next_key: thumb_three key.mirror.led_next_key: thumb_center # Mirror the thumb fan mirror: ref: main_five_bottom shift: [ 0.5cx, 0.5cy ] distance: split_gap_width # Single key centered between thumb keys thumb_center: anchor: # Center between the two inner thumb keys aggregate.parts: - thumb_four - mirror_thumb_four shift: [ 0, -0.25cy ] # Key settings (instead of rows/columns) key: width: 1.5kcx row_net: ROW1 column_net: COL8 led_next_key: thumb_four tags: [ is_key, 1_5u ] # Arrow keys in the middle of the keyboard # In the matrix, these keys act as 4 keys in a single column (column 8, row 2 to 5) arrow_keys: anchor: # Center between the V and B keys, then shift down half a key aggregate.parts: - main_five_bottom - main_six_bottom shift: [ 0, -cy/2 ] # Assign all keys to the same column key: column_net: COL8 rows: # Bottom row: Only the down key bottom: row_net: ROW2 tags: [ is_key, flip_led ] # Center row: Left and right keys (shifted to the left to center them) center: adjust.shift: [ -cx/2, 0 ] # Use ROW3 for the left key and ROW5 for the right key (overridden in columns) row_net: ROW3 # Top row: Only the up key top: row_net: ROW4 tags: [ is_key, flip_led ] columns: # Left column: Up, left, down keys left: rows.top: name: arrow_keys_up led_next_key: main_six_top rows.center: name: arrow_keys_left led_next_key: main_five_home rows.bottom: name: arrow_keys_down led_next_key: main_six_bottom # Right column: Only right key (assigned to matrix row 5) right: rows.top.skip: true rows.center: name: arrow_keys_right row_net: ROW5 led_next_key: arrow_keys_left rows.bottom.skip: true # Function key row above the main zone (Esc, F1-F12) function: # Position function key row above main zone with 3mm of vertical offset anchor: # To center the F keys on the top of the keyboard: # - Get center point between keys 3 and 8 (they have the highest staggering) # - Shift upwards by one key + an offset to have a small gap # - Shift to the left by 7 keys (Esc, F1-F6) + the gaps between the F key groups. aggregate.parts: - main_three_numbers - main_eight_numbers shift: [ -6.5cx - 2 * function_gap, cy + function_offset ] # Single row zone: Assign row net key: row_net: ROW6 tags: [ is_key, flip_led ] # Define function keys columns: # Escape key esc: key.shift: [ 0, -cy/8 ] key.column_net: COL1 key.led_next_key: function_f1 # Esc is the first key in the RGB LED chain. # The first LED needs to run on a lower voltage (see explanation below). key.led_vcc_net: VCC_first_led # Block of 4 keys with gap f1: key.spread: cx + function_gap key.column_net: COL2 key.led_next_key: function_f2 f2: key.column_net: COL3 key.led_next_key: function_f3 f3: key.column_net: COL4 key.led_next_key: function_f4 f4: key.column_net: COL5 key.led_next_key: function_f5 # Block of 4 keys with gap f5: key.spread: cx + function_gap key.column_net: COL6 key.led_next_key: function_f6 f6: key.column_net: COL7 key.led_next_key: function_f7 # Skip matrix column 8 (arrow keys) f7: key.column_net: COL9 key.led_next_key: function_f8 f8: key.column_net: COL10 key.led_next_key: function_f9 # Block of 4 keys with gap f9: key.spread: cx + function_gap key.column_net: COL11 key.led_next_key: function_f10 f10: key.column_net: COL12 key.led_next_key: function_f11 f11: key.column_net: COL13 key.led_next_key: function_f12 f12: key.column_net: COL14 key.led_next_key: main_twelve_numbers # RP2040 Pico Mini controller board controller: anchor: # Place in the center of the keyboard, above the arrow keys aggregate.parts: - main_five_numbers - main_six_numbers shift: [ 0, 1.5 ] # This is an auxiliary point to place the controller, not an actual key key: tags: [ is_controller ] width: 18 height: 36 # Rotary encoder in the center of the keyboard (on top of the controller board) rotary_center: anchor: ref: controller rotate: -90 key: tags: [ is_rotary_encoder ] width: 2 * rotary_encoder_radius height: 2 * rotary_encoder_radius # Matrix position of the switch: between F7 and F8 row_net: ROW6 column_net: COL8 # Rotary encoder in the top right corner of the keyboard rotary_top_right: anchor: ref: function_f12 shift: [ cx + 2 + function_gap, -cy/8 ] key: tags: [ is_rotary_encoder ] width: 2 * rotary_encoder_radius height: 2 * rotary_encoder_radius # Matrix position of the switch: Function row, right of F12 row_net: ROW6 column_net: COL15 # Generate outlines that can be used in the PCB and for 3D models outlines: # Outline of the key caps keys: # 1u keys - what: rectangle operation: stack where: [ [ is_key, -1_5u ] ] size: [ kcx, kcy ] # 1.5u keys - what: rectangle operation: stack where: [ [ is_key, 1_5u ] ] size: [ 1.5kcx, kcy ] # Rotary encoder with knob (2cm) rotary_encoder: - what: rectangle operation: stack size: [ 14, 14 ] - what: circle operation: stack radius: rotary_encoder_radius # Outline for the PCB board_outline: - what: polygon points: # Top left corner - ref: &corner_top_left_anchor - ref: main_left_numbers affect: x - ref: function_f1 affect: y - shift: [ -0.5kcx, 0.5kcy ] # Extend all corners 4mm to the sides to get a 4mm border shift: [ -4, 4 ] # Top right corner - ref: &corner_top_right_anchor - ref: main_twelve_numbers affect: x - ref: function_f12 affect: y - shift: [ 0.5kcx, 0.5kcy ] shift: [ 4, 4 ] # Bottom right corner - ref: - ref: main_twelve_mods shift: [ 0.5kcx, -0.5kcy ] shift: [ 4, -4 ] # Bottom center-right corner (below thumb keys) - ref: - ref: mirror_thumb_four shift: [ 0.5kcx, -0.5kcy ] # Discard the rotation, so the next shift moves the corner straight down affect: xy shift: [ 0, -4 ] # Bottom center-left corner (below thumb keys) - ref: - ref: thumb_four shift: [ 0.5kcx, -0.5kcy ] # Discard the rotation, so the next shift moves the corner straight down affect: xy shift: [ 0, -4 ] # Bottom left corner - ref: - ref: main_left_mods shift: [ -0.5kcx, -0.5kcy ] shift: [ -4, -4 ] # Round off the corners with an 8mm radius fillet. # NOTE: To get a smoother arc on the bottom of the board, do some post-processing in KiCad: # 1. Remove the bottom center line and the two small fillet arcs next to it. # 2. Select the two remaining bottom lines. Right click them and use "Shape Modification -> Extend Lines to Meet". # 3. Right click the two angled lines again. Use "Shape Modification -> Fillet Lines..." with a 200mm radius. fillet: 8 # Preview version of board with key caps and components for visualization board_preview: - board_outline - ^keys # RP2040 Pico Mini controller board - what: rectangle operation: stack where: is_controller size: [ 18, 36 ] # Rotary encoder - what: outline name: rotary_encoder operation: stack where: is_rotary_encoder # Cutouts for the switches switch_cutouts: - what: rectangle where: is_key size: 14 # Board outline with switch cutouts switch_plate: - board_outline - -switch_cutouts # Generate the PCB pcbs: eepyboard: # Define outline (edges) of the board based on the outlines defined above outlines: main: outline: board_outline # Define PCB components footprints: controller: what: rp2040_pico_mini where: is_controller params: # Mount the controller board on the backside of the PCB orientation: down # Use 5V from USB as VCC net 5V: VCC # RGB LEDs: The chain starts with the Esc key GP29: led_din_function_esc # Matrix columns GP27: COL1 GP26: COL2 GP25: COL3 GP23: COL4 GP22: COL5 GP21: COL6 GP20: COL7 GP17: COL8 # Center column (arrow keys) GP12: COL9 GP11: COL10 GP10: COL11 GP9: COL12 GP8: COL13 GP7: COL14 GP6: COL15 # Matrix rows GP13: ROW1 GP14: ROW2 GP19: ROW3 GP18: ROW4 GP15: ROW5 GP28: ROW6 # Rotary encoders GP0: rotary_top_right_a GP1: rotary_top_right_b GP3: rotary_center_a GP2: rotary_center_b 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: "diode_{{name}}" to: "{{column_net}}" key_diode: what: diode_smd where: is_key adjust: shift: [ 7, -7.5 ] rotate: 90 resist: true params: side: B from: "diode_{{name}}" to: "{{row_net}}" rotary_encoder: what: rotary_encoder_ec12 where: is_rotary_encoder params: from: "diode_{{name}}" to: "{{column_net}}" A: "{{name}}_a" B: "{{name}}_b" C: GND rotary_encoder_diode: $extends: pcbs.eepyboard.footprints.key_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_din_{{name}}" dout: "led_din_{{led_next_key}}" VCC: "{{led_vcc_net}}" led_capacitor: what: capacitor_smd_1206 where: [ [ is_key, -flip_led ] ] adjust: shift: [ -6, 4.5 ] rotate: 90 resist: true params: side: B from: "{{led_vcc_net}}" 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 # The first SK6812 chip in the chain has to run on a reduced voltage to serve as a makeshift level converter for # all following RGB LEDs. # This is needed because 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. first_led_voltage_diode: what: diode_smd where: function_esc adjust: shift: [ 9.5, 2.25 ] rotate: -90 params: side: B from: VCC to: VCC_first_led # Mounting holes: Top left and right corners mounting_hole_top_left: what: mountinghole_m2 where: ref: *corner_top_left_anchor shift: [ 2, -2 ] mounting_hole_top_right: what: mountinghole_m2 where: ref: *corner_top_right_anchor shift: [ -2, -2 ] # Mounting holes: Top center, left and right of the controller mounting_hole_controller_left: what: mountinghole_m2 where: ref: main_five_numbers shift: [ 0, 12 ] mounting_hole_controller_right: what: mountinghole_m2 where: ref: main_six_numbers shift: [ 0, 12 ] # Mounting holes: Bottom center, under columns five/six (but above the thumb keys) mounting_hole_bottom_center_left: what: mountinghole_m2 where: ref: main_five_bottom shift: [ 0, -13 ] mounting_hole_bottom_center_right: what: mountinghole_m2 where: ref: main_six_bottom shift: [ 0, -13 ] # Mounting holes: Bottom left and right corners, under the second key columns mounting_hole_bottom_left: what: mountinghole_m2 where: ref: main_zero_mods shift: [ 0, -13.5 ] mounting_hole_bottom_right: what: mountinghole_m2 where: ref: main_eleven_mods shift: [ 0, -13.5 ] # Render text with project name and copyright onto the PCB copyright_text: what: text where: ref: thumb_one shift: [ 0, -16.5 ] rotate: -0.3 # total rotation: -6.3 (including key rotation) params: text: |- eepyBoard v1.1 by binaryDiv (c) 2024 (MIT License)