dumped stuff from old repo

This commit is contained in:
Ricardo (XenGi) Band 2020-04-30 17:49:40 +02:00
commit cf00c83596
No known key found for this signature in database
GPG key ID: 1A9D657D06B5820E
6 changed files with 494 additions and 2 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.scad
__pycache__/
*.pyc
.venv

View file

@ -1,3 +1,74 @@
# case
# mkbd65 case
CAD files for the case of mkbd65
## Generate CAD files
OpenSCAD Files can be created with the following command:
```
./generate_scad.py
```
You need solidpython installed for it to work. Do that by executing:
```
# creates a virtualenv
python -m venv venv
# activates it
source venv/bin/activate
# installs dependencies
pip install -r requirements.txt
```
## Layout files
These files define the layoout that gets printed on the keymat. Currently the only file included is `layout_en_us.py`
for an english US international layout. you can use that as a template for your layout.
The file should define a single variable `LAYOUT` which is a list of roaws. These rows are also lists of columns. Each
column has keys, which are a list of the strings that should be printed at different positions.
Example for a one button keyboard with the labels `foo` in the top left corner and `bar` in the bottom left:
```
LAYOUT = [
[
['foo', 'bar', '', '', ''],
],
]
```
The label string will be used as `[TopLeft, BottomLeft, TopRight, BottomRight, Middle]`.
Some strings need special escaping to be used in OpenScad later on. See the en_us layout for examples.
## Phone config
Properties for different phones are saved in INI files. Currently the only file included is `oneplus5t.ini` for the
Oneplus 5t phone with a english US international layout with the DejaVu Sans font.
In the config file you can define phone specific aspects and style such as the used font and layout. Here is a list of
the possile options:
| Group | Option | Type | Default | Description |
| ------ | --------- | ------ | ---------------------- | ----------------------------- |
| keymap | thickness | Number | 0.5 | Thickness of the keymap in mm |
| | layout | String | en_us-intl | Layout file used for labels |
| key | thickness | Number | 1 | Thickness of the key in mm |
| | font | String | DejaVu Sans:style=Bold | Font used for labels |
OpenScad files
--------------
The generator script `generate_scad.py` creates multiple files.
| File | Material | Description |
| --------------------- | -------- | --------------------------------------------------- |
| mkbd65_keymat.scad | TPU | Keymat should be printed with a 3D printer |
| mkbd65_pcb.scad | - | Just a spacer for the 3D model fitting |
| mkbd65_top_plate.scad | Aluminum | Laser cut on a CNC |
| mkbd65_internals.scad | ABS/PLA | Inner structure should be printed with a 3D printer |
| mkbd65.scad | - | Combination of the above files |
CAD files for the case of mkbd65

322
generate_scad.py Executable file
View file

@ -0,0 +1,322 @@
#!/usr/bin/env python3
"""
mkbd65 openscad generator
Usage:
python3 generate_scad.py <config.ini> [<layout>]
Options:
-h --help Show this screen.
Example:
python3 generate_scad.py oneplus5t.ini en_us-intl
"""
import sys
from configparser import ConfigParser
from importlib import import_module
from solid import cube, text, union, difference, linear_extrude, scad_render_to_file, OpenSCADObject, translate, color, \
polygon, circle
from solid.utils import Black, White, Green, Aluminum, Cyan
def roundrect(width, height, radius):
"""
O/-----\O
/ \
| |
\ /
O\_____/O
:param width:
:param height:
:param radius:
:return:
"""
return union()(
polygon([
[0, radius],
[0, height - radius],
[radius, height],
[width - radius, height],
[width, height - radius],
[width, radius],
[width - radius, 0],
[radius, 0]
]),
translate([radius, radius, 0])(
circle(r=radius)
),
translate([radius, height - radius, 0])(
circle(r=radius)
),
translate([width - radius, height - radius, 0])(
circle(r=radius)
),
translate([width - radius, radius, 0])(
circle(r=radius)
)
)
def key(dx: int, dy: int, label_ltop: str = '', label_lbottom: str = '', label_rtop: str = '', label_rbottom: str = '',
label_center: str = '') -> OpenSCADObject:
"""
Generates a single key
:param dx: width in mm
:param dy: length in mm
:param label: List of labels (top, bottom, right, middle)
:return:
"""
def get_size(s: str) -> float:
if s in ['⇧', '⏎']:
return 5
elif s == '⌫':
return 3.5
elif s in ['Esc', 'Ctrl', 'Alt', 'Fn']:
return 3
else:
return 4
thickness = config.getfloat('key', 'thickness', fallback=1)
font = config.get('key', 'font', fallback='DejaVu Sans:style=Bold')
return difference()(
linear_extrude(height=thickness)(
roundrect(width=dx, height=dy, radius=0.5)
),
translate(v=[1, 5.5, 0.8])(
linear_extrude(height=0.2)(
text(text=label_ltop, size=3, font=font, halign='left', valign='top')
)
),
translate(v=[1, 0.5, 0.8])(
linear_extrude(height=0.2)(
text(text=label_lbottom, size=3, font=font, halign='left', valign='bottom')
)
),
translate(v=[8.5, 5.5, 0.8])(
linear_extrude(height=0.2)(
text(text=label_rtop, size=3, font=font, halign='right', valign='top')
)
),
translate(v=[8.5, -1.5 if label_rbottom == '`' else 0.5, 0.8])(
linear_extrude(height=0.2)(
text(text=label_rbottom, size=3, font=font, halign='right', valign='bottom')
)
),
translate(v=[4.5, 3, 0.8])(
linear_extrude(height=0.2)(
text(text=label_center, size=get_size(label_center), font=font, halign='center', valign='center')
)
)
)
def keymat() -> OpenSCADObject:
"""
Generates keymat
mat:
+---------------------------------------------+
| margin |
| +-----+ +-----+ +-----+ |
|margin| |padding| | ... | |margin|
| +-----+ +-----+ +-----+ |
| padding |
| +-----+ +-----+ +-----+ |
| | | | | | | |
| +-----+ +-----+ +-----+ |
| ... |
| +-----+ +-----+ +-----+ |
| | | | | | | |
| +-----+ +-----+ +-----+ |
| margin |
+---------------------------------------------+
\ thickness
key:
+-----+
| | dy
+-----+
dx \ thickness
:return:
"""
thickness = config.getfloat('keymat', 'thickness', fallback=0.5)
cols = 12
rows = 5
key_dx = 9
key_dy = 6
padding = 1
margin = 2
spacebar_x = 5 # nth key from the left
spacebar_length = 2 # length in keys
keys = []
for row in range(rows):
for col in range(cols):
keys.append(
translate([
col * padding + col * key_dx + margin,
row * padding + row * key_dy + margin,
thickness
])(
key(
dx=key_dx,
dy=key_dy,
label_ltop=layout[row][col][0],
label_lbottom=layout[row][col][1],
label_rtop=layout[row][col][2],
label_rbottom=layout[row][col][3],
label_center=layout[row][col][4]
)
)
)
return color(Black)(
union()(
# mat
cube([
cols * key_dx + (cols - 1) * padding + 2 * margin,
rows * key_dy + (rows - 1) * padding + 2 * margin,
thickness
]),
# keys
*keys,
# spacebar
translate([spacebar_x * key_dx + spacebar_x * padding + margin, margin, thickness])(
key(dx=key_dx * spacebar_length + (spacebar_length - 1) * padding, dy=key_dy)
)
)
)
def pcb() -> OpenSCADObject:
rows = 5
columns = 12
hspacing = 4
vspacing = 3
width = 6
height = 4
thickness = 0.78
switches = []
for row in range(rows):
for col in range(columns):
switches.append(
translate([3.5 + (hspacing + width) * col, 2 + (vspacing + height) * row, 0.6])(
color(White)(
linear_extrude(height=thickness)(
# 6 +----+ 5
# / \
# 7 + + 4 | 2mm
# 8 + + 3 |
# \ 4mm /
# 1 +----+ 2
polygon(points=[(1, 0), (5, 0), (6, 1), (6, 3), (5, 4), (1, 4), (0, 3), (0, 1)]),
)
)
)
)
return union()(
color(Green)(cube([123, 49, 0.6])),
# ATMEGA32U4
translate([13, 36, 0.6])(
color(Black)(cube([7, 7, 1]))
),
# Crystal
translate([23, 35.75, 0.6])(
color(Black)(cube([2.5, 2, 0.55]))
),
*switches
)
def top_plate() -> OpenSCADObject:
thickness = config.getfloat('keymat', 'thickness', fallback=1)
w = config.getfloat('phone', 'width')
h = config.getfloat('phone', 'height')
r = config.getfloat('phone', 'cornerradius')
return color(Aluminum)(
difference()(
#cube([123, 49, 0.5]),
linear_extrude(height=thickness)(
roundrect(width=w, height=h, radius=r)
),
translate([0, 0, -1 * thickness])(keymat())
)
)
def internals() -> OpenSCADObject:
return color(Cyan)(cube([1, 1, 1]))
def mkbd65() -> OpenSCADObject:
fr4 = 0.4 # pcb thickness
switch = 0.78 # switch height
keymat_thickness = config.getfloat('keymat', 'thickness', fallback=1)
return union()(
internals(),
pcb(),
color(Black)(translate([0, -1, fr4 + switch])(keymat())),
color(Aluminum)(translate([0, -1, fr4 + switch + keymat_thickness])(top_plate()))
)
if __name__ == '__main__':
config = ConfigParser()
if '-h' in sys.argv or '--help' in sys.argv or 2 > len(sys.argv) > 3:
sys.exit(__doc__)
if len(sys.argv) == 3:
layoutfile = sys.argv[2]
else:
layoutfile = 'en_us-intl'
try:
with open(sys.argv[1]) as fd:
config.read_file(fd)
layout = import_module(f'layout_{ layoutfile }').LAYOUT
file_header = '$fn = 16;'
scad_render_to_file(
keymat(),
filepath='./mkbd65_keymat.scad',
file_header=file_header,
)
# TODO: generate mkbd65_pcb.scad
scad_render_to_file(
pcb(),
filepath='./mkbd65_pcb.scad',
file_header=file_header,
)
# TODO: generate mkbd65_top_plate.scad
scad_render_to_file(
top_plate(),
filepath='./mkbd65_top_plate.scad',
file_header=file_header,
)
# TODO: generate mkbd65_internals.scad
scad_render_to_file(
internals(),
filepath='./mkbd65_internals.scad',
file_header=file_header,
)
# TODO: generate mkbd65.scad
scad_render_to_file(
mkbd65(),
filepath='./mkbd65.scad',
file_header=file_header,
)
except FileNotFoundError:
sys.exit(f'The config file { sys.argv[1] } could not be found.')
except ModuleNotFoundError:
sys.exit(f'The layout file `layout_{ layoutfile }.py` could not be found.')

80
layout_en_us-intl.py Normal file
View file

@ -0,0 +1,80 @@
# [TopLeft, BottomLeft, TopRight, BottomRight, Middle]
LAYOUT = [
# row 4
[
['', '', '', '', 'Ctrl'], # Left Control
['', '', '', '', 'Fn'], # Function
['', '', '', '', '⇧'], # Left Shift
['', '', '', '', 'Alt'], # Left Alt (Alt Gr)
['', '\\\\', '|', '', ''],
['', '', '', '', ''], # Spacebar (won't be visible)
['', '', '', '', ''], # Spacebar (won't be visible)
['', '-', '_', '', ''],
['', '=', '+', '', ''],
['', '', '', '', '◀'], # Arrow Left / Home
['', '', '', '', '▼'], # Arrow Down / Page Down
['', '', '', '', '▶'] # Arrow Right / End
],
# row 3
[
['', '', '', '', 'Z'],
['', '', '', '', 'X'],
['', '', '', '', 'C'],
['', '', '', '', 'V'],
['', '', '', '', 'B'],
['', '', '', '', 'N'],
['', '', '', '', 'M'],
['', ',', '<', '', ''],
['', '.', '>', '', ''],
['', '/', '?', '', ''],
['', '', '', '', '▲'], # Arrow Up / Page Up
['', '', '', '', '⇧'] # Right Shift
],
# row 2
[
['', '', '', '', 'A'],
['', '', '', '', 'S'],
['', '', '', '', 'D'],
['', '', '', '', 'F'],
['', '', '', '', 'G'],
['', '', '', '', 'H'],
['', '', '', '', 'J'],
['', '', '', '', 'K'],
['', '', '', '', 'L'],
['', ';', ':', '', ''],
['', '\'', '\\"', '`', ''],
['', '', '', '', '⏎'] # Return
],
# row 1
[
['', '', '', '', 'Q'],
['', '', '', '', 'W'],
['', '', '', '', 'E'],
['', '', '', '', 'R'],
['', '', '', '', 'T'],
['', '', '', '', 'Y'],
['', '', '', '', 'U'],
['', '', '', '', 'I'],
['', '', '', '', 'O'],
['', '', '', '', 'P'],
['', '[', '{', '', ''],
['', ']', '}', '', '']
],
# row 0
[
['','','','','Esc'],
['', '1', '!', '', ''],
['', '2', '@', '', ''],
['', '3', '#', '', ''],
['', '4', '$', '', ''],
#['', '5', '%', '€', ''],
['', '5', '%', '', ''],
['', '6', '^', '', ''],
['', '7', '&', '', ''],
['', '8', '*', '', ''],
['', '9', '(', '', ''],
['', '0', ')', '', ''],
['', '', '', '', '⌫'] # Backspace
]
]

14
oneplus5t.ini Normal file
View file

@ -0,0 +1,14 @@
; mkbd65 config for OnePlus 5t
[keymat]
thickness = 0.5
layout = en_us-intl
[key]
thickness = 1
font = DejaVu Sans:style=Bold
[phone]
width = 156
height = 75
cornerradius = 10

1
requirements.txt Normal file
View file

@ -0,0 +1 @@
solidpython