Merge master and reconcile tapdance with splits
This took a bit of brain surgery to firmware.py that deserves its own commit message beyond the default merge commit message - tl;dr though, it appears to work fine.
This commit is contained in:
commit
94ac6d0cbd
3
.gitignore
vendored
3
.gitignore
vendored
@ -112,3 +112,6 @@ venv.bak/
|
||||
|
||||
# Pycharms cruft
|
||||
.idea
|
||||
|
||||
# Personal dev scripts
|
||||
.scripts
|
||||
|
38
docs/split_keyboards.md
Normal file
38
docs/split_keyboards.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Split Keyboards
|
||||
Split keyboards are mostly the same as unsplit and very easy to adapt a keymap for. Currently
|
||||
UART is supported, though other modes will come later such as Bluetooth and i2c.
|
||||
|
||||
Useful config options:
|
||||
```python
|
||||
keyboard.split_flip = True # If your boards are identical but one is flipped, this option is for you
|
||||
keyboard.split_offsets = [6, 6, 6, 6] # This is the how many keys are on each column on the "Master" half
|
||||
```
|
||||
|
||||
## Master Half
|
||||
Choosing the master half can be done one of 2 ways. You can set this true or false if you only pleg in on one side.
|
||||
```python
|
||||
keyboard.split_master_left = True
|
||||
```
|
||||
|
||||
## EE HANDS
|
||||
If you want to plug in on either side, it can be done fairly easily but requires setup.
|
||||
|
||||
On each half of your keyboard make a file called kmk_side.py and add one of these lines to the file
|
||||
depending on where each piece is physically located.
|
||||
```python
|
||||
split_side = "Left"
|
||||
OR
|
||||
split_side = "Right"
|
||||
```
|
||||
|
||||
and then in your keymap, add the line
|
||||
```python
|
||||
from kmk_side import split_side
|
||||
```
|
||||
|
||||
# UART
|
||||
To enable uart it's as simple as adding this line, of course changing the pin
|
||||
```python
|
||||
keyboard.split_type = "UART"
|
||||
keyboard.uart = keyboard.init_uart(tx=board.SCL)
|
||||
```
|
103
kmk/firmware.py
103
kmk/firmware.py
@ -34,8 +34,10 @@ import kmk.internal_state # isort:skip
|
||||
|
||||
# Thanks for sticking around. Now let's do real work, starting below
|
||||
|
||||
import busio
|
||||
import gc
|
||||
|
||||
import supervisor
|
||||
from kmk.consts import LeaderMode, UnicodeModes
|
||||
from kmk.hid import USB_HID
|
||||
from kmk.internal_state import InternalState
|
||||
@ -59,6 +61,15 @@ class Firmware:
|
||||
|
||||
hid_helper = USB_HID
|
||||
|
||||
split_offsets = ()
|
||||
split_flip = False
|
||||
split_side = None
|
||||
split_type = None
|
||||
split_master_left = True
|
||||
is_master = None
|
||||
uart = None
|
||||
uart_flip = True
|
||||
|
||||
def __init__(self):
|
||||
self._state = InternalState(self)
|
||||
|
||||
@ -75,12 +86,78 @@ class Firmware:
|
||||
self._state.remove_key(key)
|
||||
self._send_hid()
|
||||
|
||||
def _handle_matrix_report(self, update=None):
|
||||
'''
|
||||
Bulk processing of update code for each cycle
|
||||
:param update:
|
||||
'''
|
||||
if update is not None:
|
||||
self._state.matrix_changed(
|
||||
update[0],
|
||||
update[1],
|
||||
update[2],
|
||||
)
|
||||
|
||||
def _send_to_master(self, update):
|
||||
if self.split_master_left:
|
||||
update[1] += self.split_offsets[update[0]]
|
||||
else:
|
||||
update[1] -= self.split_offsets[update[0]]
|
||||
if self.uart is not None:
|
||||
self.uart.write(update)
|
||||
|
||||
def _receive_from_slave(self):
|
||||
if self.uart is not None and self.uart.in_waiting > 0:
|
||||
update = bytearray(self.uart.read(3))
|
||||
# Built in debug mode switch
|
||||
if update == b'DEB':
|
||||
# TODO Pretty up output
|
||||
print(self.uart.readline())
|
||||
return None
|
||||
return update
|
||||
|
||||
return None
|
||||
|
||||
def _send_debug(self, message):
|
||||
'''
|
||||
Prepends DEB and appends a newline to allow debug messages to
|
||||
be detected and handled differently than typical keypresses.
|
||||
:param message: Debug message
|
||||
'''
|
||||
if self.uart is not None:
|
||||
self.uart.write('DEB')
|
||||
self.uart.write(message, '\n')
|
||||
|
||||
def _master_half(self):
|
||||
return supervisor.runtime.serial_connected
|
||||
|
||||
def init_uart(self, tx=None, rx=None, timeout=20):
|
||||
if self._master_half():
|
||||
# If running with one wire, only receive on master
|
||||
if rx is None or self.uart_flip:
|
||||
return busio.UART(tx=rx, rx=None, timeout=timeout)
|
||||
else:
|
||||
return busio.UART(tx=tx, rx=rx, timeout=timeout)
|
||||
|
||||
else:
|
||||
return busio.UART(tx=tx, rx=rx, timeout=timeout)
|
||||
|
||||
def go(self):
|
||||
assert self.keymap, 'must define a keymap with at least one row'
|
||||
assert self.row_pins, 'no GPIO pins defined for matrix rows'
|
||||
assert self.col_pins, 'no GPIO pins defined for matrix columns'
|
||||
assert self.diode_orientation is not None, 'diode orientation must be defined'
|
||||
|
||||
self.is_master == self._master_half()
|
||||
|
||||
if self.split_flip and not self._master_half():
|
||||
self.col_pins = list(reversed(self.col_pins))
|
||||
|
||||
if self.split_side == "Left":
|
||||
self.split_master_left = self.is_master
|
||||
elif self.split_side == "Right":
|
||||
self.split_master_left = not self.is_master
|
||||
|
||||
self.matrix = MatrixScanner(
|
||||
cols=self.col_pins,
|
||||
rows=self.row_pins,
|
||||
@ -95,18 +172,24 @@ class Firmware:
|
||||
print("Firin' lazers. Keyboard is booted.")
|
||||
|
||||
while True:
|
||||
matrix_report = self.matrix.scan_for_changes()
|
||||
state_changed = False
|
||||
|
||||
if matrix_report is not None:
|
||||
self._state.matrix_changed(
|
||||
matrix_report[0],
|
||||
matrix_report[1],
|
||||
matrix_report[2],
|
||||
)
|
||||
|
||||
if self.split_type is not None and self._master_half:
|
||||
update = self._receive_from_slave()
|
||||
if update is not None:
|
||||
self._handle_matrix_report(update)
|
||||
state_changed = True
|
||||
|
||||
update = self.matrix.scan_for_changes()
|
||||
|
||||
if update is not None:
|
||||
if self._master_half():
|
||||
self._handle_matrix_report(update)
|
||||
state_changed = True
|
||||
else:
|
||||
# This keyboard is a slave, and needs to send data to master
|
||||
self._send_to_master(update)
|
||||
|
||||
if self._state.hid_pending:
|
||||
self._send_hid()
|
||||
|
||||
@ -118,12 +201,14 @@ class Firmware:
|
||||
state_changed = True
|
||||
|
||||
if self._state.macros_pending:
|
||||
# Blindly assume macros are going to change state, which is almost
|
||||
# always a safe assumption
|
||||
state_changed = True
|
||||
for macro in self._state.macros_pending:
|
||||
for key in macro(self):
|
||||
self._send_key(key)
|
||||
|
||||
self._state.resolve_macro()
|
||||
state_changed = True
|
||||
|
||||
if self.debug_enabled and state_changed:
|
||||
print('New State: {}'.format(self._state._to_dict()))
|
||||
|
@ -16,9 +16,9 @@ keyboard.diode_orientation = DiodeOrientation.COLUMNS
|
||||
|
||||
# ------------------User level config variables ---------------------------------------
|
||||
keyboard.unicode_mode = UnicodeModes.LINUX
|
||||
keyboard.tap_time = 900
|
||||
keyboard.tap_time = 350
|
||||
keyboard.leader_timeout = 2000
|
||||
keyboard.debug_enabled = True
|
||||
keyboard.debug_enabled = False
|
||||
|
||||
emoticons = compile_unicode_string_sequences({
|
||||
# Emoticons, but fancier
|
||||
|
99
user_keymaps/kdb424/levinson_m4.py
Normal file
99
user_keymaps/kdb424/levinson_m4.py
Normal file
@ -0,0 +1,99 @@
|
||||
import board
|
||||
import busio
|
||||
|
||||
from kmk.consts import DiodeOrientation, LeaderMode, UnicodeModes
|
||||
from kmk.keycodes import KC
|
||||
from kmk.keycodes import generate_leader_dictionary_seq as glds
|
||||
from kmk.macros.simple import send_string
|
||||
from kmk.macros.unicode import compile_unicode_string_sequences
|
||||
from kmk.mcus.circuitpython_samd51 import Firmware
|
||||
from kmk.pins import Pin as P
|
||||
from kmk.types import AttrDict
|
||||
|
||||
keyboard = Firmware()
|
||||
|
||||
keyboard.col_pins = (P.D10, P.D9, P.D7, P.D5, P.A4, P.A5)
|
||||
keyboard.row_pins = (P.A0, P.A1, P.A2, P.A3)
|
||||
keyboard.diode_orientation = DiodeOrientation.COLUMNS
|
||||
|
||||
keyboard.split_type = "UART"
|
||||
keyboard.split_flip = True
|
||||
keyboard.split_offsets = [6, 6, 6, 6]
|
||||
keyboard.uart_flip = False
|
||||
keyboard.uart = keyboard.init_uart(tx=board.TX, rx=board.RX)
|
||||
|
||||
# ------------------User level config variables ---------------------------------------
|
||||
keyboard.leader_mode = LeaderMode.TIMEOUT
|
||||
keyboard.unicode_mode = UnicodeModes.LINUX
|
||||
keyboard.tap_time = 150
|
||||
keyboard.leader_timeout = 2000
|
||||
keyboard.debug_enabled = True
|
||||
|
||||
emoticons = compile_unicode_string_sequences({
|
||||
# Emoticons, but fancier
|
||||
'ANGRY_TABLE_FLIP': r'(ノಠ痊ಠ)ノ彡┻━┻',
|
||||
'CHEER': r'+。:.゚ヽ(´∀。)ノ゚.:。+゚゚+。:.゚ヽ(*´∀)ノ゚.:。+゚',
|
||||
'TABLE_FLIP': r'(╯°□°)╯︵ ┻━┻',
|
||||
'WAT': r'⊙.☉',
|
||||
'FF': r'凸(゚Д゚#)',
|
||||
'F': r'( ̄^ ̄)凸',
|
||||
'MEH': r'╮( ̄_ ̄)╭',
|
||||
'YAY': r'o(^▽^)o',
|
||||
})
|
||||
|
||||
# ---------------------- Leader Key Macros --------------------------------------------
|
||||
|
||||
keyboard.leader_dictionary = {
|
||||
glds('flip'): emoticons.ANGRY_TABLE_FLIP,
|
||||
glds('cheer'): emoticons.CHEER,
|
||||
glds('wat'): emoticons.WAT,
|
||||
glds('ff'): emoticons.FF,
|
||||
glds('f'): emoticons.F,
|
||||
glds('meh'): emoticons.MEH,
|
||||
glds('yay'): emoticons.YAY,
|
||||
}
|
||||
|
||||
WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.")
|
||||
|
||||
# ---------------------- Keymap ---------------------------------------------------------
|
||||
|
||||
keyboard.keymap = [
|
||||
[
|
||||
# Default
|
||||
[KC.GESC, KC.QUOTE, KC.COMMA, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BKSP],
|
||||
[KC.TAB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT],
|
||||
[KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH],
|
||||
[KC.LCTRL, KC.LGUI, KC.LALT, KC.LEAD, KC.MO(2), KC.LT(3, KC.SPC), KC.LT(3, KC.SPC), KC.MO(4), KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT],
|
||||
],
|
||||
[
|
||||
# Gaming
|
||||
[KC.TAB, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BKSP],
|
||||
[KC.ESC, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT],
|
||||
[KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH],
|
||||
[KC.LCTRL, KC.LGUI, KC.LALT, KC.F1, KC.F2, KC.SPC, KC.SPC, KC.MO(4), KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT],
|
||||
],
|
||||
[
|
||||
# Raise1
|
||||
[KC.TILD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL],
|
||||
[KC.TRNS, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.LBRC, KC.RBRC, KC.BSLS],
|
||||
[KC.TRNS, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.INS, KC.PGDN, KC.PGUP, KC.MINS],
|
||||
[KC.RESET, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.NO, KC.NO, KC.EQL, KC.HOME, KC.VOLD, KC.VOLU, KC.END],
|
||||
],
|
||||
[
|
||||
# Raise2
|
||||
[KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N7, KC.N8, KC.N9, KC.BKSP],
|
||||
[KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N4, KC.N5, KC.N6, KC.NO],
|
||||
[KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N1, KC.N2, KC.N3, KC.NO],
|
||||
[KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N0, KC.N0, KC.PDOT, KC.ENT],
|
||||
],
|
||||
[
|
||||
# Raise3
|
||||
[WPM, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F10, KC.F11, KC.F12, KC.LSHIFT(KC.INS)],
|
||||
[KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F7, KC.F8, KC.F9, KC.NO],
|
||||
[KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F4, KC.F5, KC.F6, KC.NO],
|
||||
[KC.DF(0), KC.DF(1), KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F1, KC.F2, KC.F3, KC.NO],
|
||||
],
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyboard.go()
|
@ -9,6 +9,7 @@ keyboard = Firmware()
|
||||
|
||||
keyboard.debug_enabled = True
|
||||
keyboard.unicode_mode = UnicodeModes.LINUX
|
||||
keyboard.tap_time = 750
|
||||
|
||||
emoticons = cuss({
|
||||
# Emojis
|
||||
|
Loading…
x
Reference in New Issue
Block a user