Keyboard: move common code to mixin (atreus21, keypad)
This commit is contained in:
parent
ec8abee265
commit
0d4d4f308b
|
@ -4,13 +4,14 @@ from copy import deepcopy
|
|||
|
||||
from boxes import Boxes, Color, holeCol, restore, boolarg
|
||||
from boxes.edges import FingerJointSettings
|
||||
from .keyboard import Keyboard
|
||||
|
||||
|
||||
class Atreus21(Boxes):
|
||||
class Atreus21(Boxes, Keyboard):
|
||||
"""Generator for a split atreus keyboard."""
|
||||
ui_group = 'Misc'
|
||||
btn_size = 15.6
|
||||
btn_outer = btn_size + 3.4
|
||||
half_btn = btn_size / 2
|
||||
border = 6
|
||||
|
||||
row_offsets=[3, 6, 11, 5, 0, btn_size * .5]
|
||||
|
@ -82,73 +83,36 @@ class Atreus21(Boxes):
|
|||
corner = [90, b]
|
||||
self.polyline(*([x, corner, y, corner] * 2))
|
||||
self.moveTo(0, b)
|
||||
|
||||
def half(self, cb=None, reverse=False):
|
||||
|
||||
def half(self, hole_cb=None, reverse=False):
|
||||
row_offsets=self.row_offsets
|
||||
row_keys=self.row_keys
|
||||
scheme = list(zip(row_offsets, row_keys))
|
||||
if reverse:
|
||||
scheme.reverse()
|
||||
for offset, keys in scheme:
|
||||
self.moveTo(0, offset)
|
||||
self.key_row(keys, cb)
|
||||
self.moveTo(self.btn_outer)
|
||||
self.moveTo(0, -offset)
|
||||
|
||||
total_moved_rows = len(row_offsets) * (self.btn_outer)
|
||||
self.moveTo(total_moved_rows * -1, 0)
|
||||
|
||||
def key_row(self, n, hole_cb=None):
|
||||
"""Callback for the key holes."""
|
||||
if hole_cb == None:
|
||||
hole_cb = self.key
|
||||
for _ in range(n):
|
||||
hole_cb()
|
||||
self.moveTo(0, -n * (self.btn_outer))
|
||||
self.moveTo(self.half_btn, self.half_btn)
|
||||
self.apply_callback_on_columns(
|
||||
hole_cb,
|
||||
scheme,
|
||||
self.STANDARD_KEY_SPACING,
|
||||
reverse,
|
||||
)
|
||||
self.moveTo(-self.half_btn, -self.half_btn)
|
||||
|
||||
def support(self):
|
||||
btn = [11.6, (-90, 2)] * 4
|
||||
self.set_source_color(Color.BLUE)
|
||||
self.moveTo(0, 2, 90)
|
||||
self.polyline(*btn)
|
||||
self.moveTo(-2, 0, 270)
|
||||
self.moveTo(0, self.btn_outer)
|
||||
self.set_source_color(Color.BLACK)
|
||||
self.outer_hole()
|
||||
|
||||
def hotplug(self):
|
||||
self.moveTo(7.8 , 7.8)
|
||||
self.hole(0, 0, d=4)
|
||||
self.hole(1.27 * -3, 1.27 * 2, d=2.9)
|
||||
self.hole(1.27 * 2, 1.27 * 4, d=2.9)
|
||||
|
||||
# pcb mounts
|
||||
self.hole(1.27 * -4, 0, d=1.7)
|
||||
self.hole(1.27 * 4, 0, d=1.7)
|
||||
|
||||
self.moveTo(-7.8, -7.8)
|
||||
self.moveTo(0, self.btn_outer)
|
||||
self.pcb_holes()
|
||||
|
||||
def key(self):
|
||||
self.set_source_color(Color.BLUE)
|
||||
|
||||
# draw clock wise to work with burn correction
|
||||
btn_half_side = [0.98, 90, 0.81, -90, 3.5, -90, 0.81, 90, 2.505]
|
||||
btn_full_side = [*btn_half_side, 0, *btn_half_side[::-1]]
|
||||
btn = [*btn_full_side, -90] * 4
|
||||
|
||||
self.moveTo(0.81, 0.81, 90)
|
||||
self.polyline(*btn)
|
||||
self.moveTo(0, 0, 270)
|
||||
self.moveTo(-0.81, -0.81)
|
||||
self.moveTo(0, self.btn_outer)
|
||||
|
||||
self.set_source_color(Color.BLACK)
|
||||
self.castle_shaped_plate_cutout()
|
||||
|
||||
# get case sizes
|
||||
def _case_x_y(self):
|
||||
x = len(self.row_offsets) * self.btn_outer - 4
|
||||
x = len(self.row_offsets) * self.STANDARD_KEY_SPACING - 4
|
||||
y = sum([
|
||||
max(self.row_keys) * self.btn_outer, # total button sizes
|
||||
max(self.row_keys) * self.STANDARD_KEY_SPACING, # total button sizes
|
||||
max(self.row_offsets), # offset of highest row
|
||||
-4,
|
||||
])
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2021 Guillaume Collic
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class Keyboard:
|
||||
"""
|
||||
Code to manage Cherry MX compatible switches and Kailh hotswap socket.
|
||||
"""
|
||||
|
||||
STANDARD_KEY_SPACING = 19
|
||||
SWITCH_CASE_SIZE = 15.6
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def pcb_holes(self):
|
||||
grid_unit = 1.27
|
||||
main_hole_size = 4
|
||||
pcb_mount_size = 1.7
|
||||
led_hole_size = 1
|
||||
pin_hole_size = 2.9
|
||||
|
||||
def grid_hole(x, y, d):
|
||||
self.hole(grid_unit * x, grid_unit * y, d=d)
|
||||
|
||||
# main hole
|
||||
grid_hole(0, 0, main_hole_size)
|
||||
|
||||
# switch pins
|
||||
grid_hole(-3, 2, pin_hole_size)
|
||||
grid_hole(2, 4, pin_hole_size)
|
||||
|
||||
grid_hole(-4, 0, pcb_mount_size)
|
||||
grid_hole(4, 0, pcb_mount_size)
|
||||
|
||||
def apply_callback_on_columns(self, cb, columns_definition, spacing, reverse=False):
|
||||
if reverse:
|
||||
columns_definition = list(reversed(columns_definition))
|
||||
|
||||
for offset, nb_keys in columns_definition:
|
||||
self.moveTo(0, offset)
|
||||
for _ in range(nb_keys):
|
||||
cb()
|
||||
self.moveTo(0, spacing)
|
||||
self.moveTo(spacing, -nb_keys * spacing)
|
||||
self.moveTo(0, -offset)
|
||||
|
||||
total_width = len(columns_definition) * spacing
|
||||
self.moveTo(-1 * total_width)
|
||||
|
||||
def outer_hole(self, radius=2, centered=True):
|
||||
"""
|
||||
Draws a rounded square big enough to go around a whole switch (15.6mm)
|
||||
"""
|
||||
half_size = Keyboard.SWITCH_CASE_SIZE / 2
|
||||
if centered:
|
||||
self.moveTo(-half_size, -half_size)
|
||||
|
||||
# draw clock wise to work with burn correction
|
||||
straight_edge = Keyboard.SWITCH_CASE_SIZE - 2 * radius
|
||||
polyline = [straight_edge, (-90, radius)] * 4
|
||||
self.moveTo(0, radius, 90)
|
||||
self.polyline(*polyline)
|
||||
self.moveTo(0, 0, 270)
|
||||
self.moveTo(0, -radius)
|
||||
self.moveTo(0)
|
||||
|
||||
if centered:
|
||||
self.moveTo(half_size, half_size)
|
||||
|
||||
def castle_shaped_plate_cutout(self, centered=True):
|
||||
"""
|
||||
This cutout shaped like a castle enables switch modding and rotation.
|
||||
More information (type 4) on https://geekhack.org/index.php?topic=59837.0
|
||||
"""
|
||||
half_size = Keyboard.SWITCH_CASE_SIZE / 2
|
||||
if centered:
|
||||
self.moveTo(-half_size, -half_size)
|
||||
|
||||
# draw clock wise to work with burn correction
|
||||
btn_half_side = [0.98, 90, 0.81, -90, 3.5, -90, 0.81, 90, 2.505]
|
||||
btn_full_side = [*btn_half_side, 0, *btn_half_side[::-1]]
|
||||
btn = [*btn_full_side, -90] * 4
|
||||
|
||||
self.moveTo(0.81, 0.81, 90)
|
||||
self.polyline(*btn)
|
||||
self.moveTo(0, 0, 270)
|
||||
self.moveTo(-0.81, -0.81)
|
||||
|
||||
if centered:
|
||||
self.moveTo(half_size, half_size)
|
|
@ -4,13 +4,16 @@ from copy import deepcopy
|
|||
|
||||
from boxes import Boxes, boolarg
|
||||
from boxes.edges import FingerJointSettings
|
||||
from .keyboard import Keyboard
|
||||
|
||||
|
||||
class Keypad(Boxes):
|
||||
class Keypad(Boxes, Keyboard):
|
||||
"""Generator for keypads with mechanical switches."""
|
||||
ui_group = 'Box'
|
||||
btn_size = 15.6
|
||||
triangle = 25.
|
||||
space_between_btn = 4
|
||||
box_padding = 10
|
||||
triangle = 25.0
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
@ -45,8 +48,8 @@ class Keypad(Boxes):
|
|||
|
||||
def _get_x_y(self):
|
||||
"""Gets the keypad's size based on the number of buttons."""
|
||||
x = self.btn_x * (self.btn_size) + (self.btn_x - 1) * 4 + 20
|
||||
y = self.btn_y * (self.btn_size) + (self.btn_y - 1) * 4 + 20
|
||||
x = self.btn_x * (self.btn_size) + (self.btn_x - 1) * self.space_between_btn + 2*self.box_padding
|
||||
y = self.btn_y * (self.btn_size) + (self.btn_y - 1) * self.space_between_btn + 2*self.box_padding
|
||||
return x, y
|
||||
|
||||
def render(self):
|
||||
|
@ -69,10 +72,10 @@ class Keypad(Boxes):
|
|||
self.rectangularWall(x, h, "GFEF", callback=[self.wallx_cb], move="left up")
|
||||
|
||||
# keypad lids
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.support_hole], move="right")
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.key_hole], move="up")
|
||||
self.rectangularWall(x, y, "ffff", callback=self.to_grid_callback(self.support_hole), move="right")
|
||||
self.rectangularWall(x, y, "ffff", callback=self.to_grid_callback(self.key_hole), move="up")
|
||||
if self.top2_enable:
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.hotplug])
|
||||
self.rectangularWall(x, y, "ffff", callback=self.to_grid_callback(self.hotplug))
|
||||
|
||||
# screwable
|
||||
tr = self.triangle
|
||||
|
@ -87,64 +90,27 @@ class Keypad(Boxes):
|
|||
callback=[None, lambda: self.hole(trh, trh, d=d1)]
|
||||
)
|
||||
|
||||
def to_grid_callback(self, inner_callback):
|
||||
scheme = [(0, self.btn_y)]*self.btn_x
|
||||
def callback():
|
||||
# move to first key center
|
||||
key_margin = self.box_padding + self.btn_size / 2
|
||||
self.moveTo(key_margin, key_margin)
|
||||
self.apply_callback_on_columns(
|
||||
inner_callback, scheme, self.btn_size + self.space_between_btn
|
||||
)
|
||||
|
||||
return [callback]
|
||||
|
||||
def hotplug(self):
|
||||
"""Callback for the key stabelizers."""
|
||||
# draw clock wise to work with burn correction
|
||||
btn = [11.6, (-90, 2)] * 4
|
||||
s = self.btn_size
|
||||
self.moveTo(10, 10)
|
||||
for _ in range(self.btn_y):
|
||||
for _ in range(self.btn_x):
|
||||
self.moveTo(7.8 , 7.8)
|
||||
|
||||
self.hole(0, 0, d=4)
|
||||
self.hole(1.27 * -3, 1.27 * 2, d=2.9)
|
||||
self.hole(1.27 * 2, 1.27 * 4, d=2.9)
|
||||
|
||||
# pcb mounts
|
||||
self.hole(1.27 * -4, 0, d=1.7)
|
||||
self.hole(1.27 * 4, 0, d=1.7)
|
||||
|
||||
self.moveTo(-7.8, -7.8)
|
||||
self.moveTo(s + 4)
|
||||
|
||||
#self.moveTo(1.27 * -2, 1.17 * 3)
|
||||
#self.moveTo(1.27 * 2, 1.17 * -3)
|
||||
self.moveTo(self.btn_x * (s + 4) * -1, s + 4)
|
||||
self.pcb_holes()
|
||||
|
||||
def support_hole(self):
|
||||
"""Callback for the key stabelizers."""
|
||||
# draw clock wise to work with burn correction
|
||||
btn = [11.6, (-90, 2)] * 4
|
||||
|
||||
s = self.btn_size
|
||||
self.moveTo(10, 10)
|
||||
for _ in range(self.btn_y):
|
||||
for _ in range(self.btn_x):
|
||||
self.moveTo(0, 2, 90)
|
||||
self.polyline(*btn)
|
||||
self.moveTo(0, 0, 270)
|
||||
self.moveTo(s + 4, -2)
|
||||
self.moveTo(self.btn_x * (s + 4) * -1, s + 4)
|
||||
self.outer_hole()
|
||||
|
||||
def key_hole(self):
|
||||
"""Callback for the key holes."""
|
||||
# draw clock wise to work with burn correction
|
||||
btn_half_side = [0.98, 90, 0.81, -90, 3.5, -90, 0.81, 90, 2.505]
|
||||
btn_full_side = [*btn_half_side, 0, *btn_half_side[::-1]]
|
||||
btn = [*btn_full_side, -90] * 4
|
||||
|
||||
s = self.btn_size
|
||||
self.moveTo(10, 10)
|
||||
for _ in range(self.btn_y):
|
||||
for _ in range(self.btn_x):
|
||||
self.moveTo(0.81, 0.81, 90)
|
||||
self.polyline(*btn)
|
||||
self.moveTo(0, 0, 270)
|
||||
self.moveTo(-0.81, -0.81)
|
||||
self.moveTo(s + 4)
|
||||
self.moveTo(self.btn_x * (s + 4) * -1, s + 4)
|
||||
self.castle_shaped_plate_cutout()
|
||||
|
||||
# stolen form electronics-box
|
||||
def wallx_cb(self):
|
||||
|
|
Loading…
Reference in New Issue