diff --git a/kmk/kmk_keyboard.py b/kmk/kmk_keyboard.py index 90f845b..8142449 100644 --- a/kmk/kmk_keyboard.py +++ b/kmk/kmk_keyboard.py @@ -112,19 +112,15 @@ class KMKKeyboard: def _handle_matrix_report(self, update=None): if update is not None: - self._on_matrix_changed(update[0], update[1], update[2]) + self._on_matrix_changed(update) self.state_changed = True - def _find_key_in_map(self, int_coord, row, col): + def _find_key_in_map(self, int_coord): try: idx = self.coord_mapping.index(int_coord) except ValueError: if self.debug_enabled: - print( - 'CoordMappingNotFound(ic={}, row={}, col={})'.format( - int_coord, row, col - ) - ) + print('CoordMappingNotFound(ic={})'.format(int_coord)) return None @@ -144,22 +140,25 @@ class KMKKeyboard: return layer_key - def _on_matrix_changed(self, row, col, is_pressed): + def _on_matrix_changed(self, kevent): + int_coord = kevent.key_number + is_pressed = kevent.pressed if self.debug_enabled: - print('MatrixChange(col={} row={} pressed={})'.format(col, row, is_pressed)) - - int_coord = intify_coordinate(row, col) + print('MatrixChange(ic={} pressed={})'.format(int_coord, is_pressed)) if not is_pressed: - self.current_key = self._coordkeys_pressed[int_coord] + try: + self.current_key = self._coordkeys_pressed[int_coord] + except KeyError: + print(f'KeyNotPressed(ic={int_coord})') if self.debug_enabled: print('PressedKeyResolution(key={})'.format(self.current_key)) if self.current_key is None: - self.current_key = self._find_key_in_map(int_coord, row, col) + self.current_key = self._find_key_in_map(int_coord) if self.current_key is None: - print('MatrixUndefinedCoordinate(col={} row={})'.format(col, row)) + print('MatrixUndefinedCoordinate(ic={})'.format(int_coord)) return self for module in self.modules: @@ -179,15 +178,15 @@ class KMKKeyboard: del self._coordkeys_pressed[int_coord] if self.current_key: - self.process_key(self.current_key, is_pressed, int_coord, (row, col)) + self.process_key(self.current_key, is_pressed, int_coord) return self - def process_key(self, key, is_pressed, coord_int=None, coord_raw=None): + def process_key(self, key, is_pressed, coord_int=None): if is_pressed: - key.on_press(self, coord_int, coord_raw) + key.on_press(self, coord_int) else: - key.on_release(self, coord_int, coord_raw) + key.on_release(self, coord_int) return self @@ -274,7 +273,9 @@ class KMKKeyboard: for ridx in range(rows_to_calc): for cidx in range(cols_to_calc): - self.coord_mapping.append(intify_coordinate(ridx, cidx)) + self.coord_mapping.append( + intify_coordinate(ridx, cidx, cols_to_calc) + ) def _init_hid(self): if self.hid_type == HIDModes.NOOP: @@ -400,6 +401,7 @@ class KMKKeyboard: self._init_sanity_check() self._init_coord_mapping() self._init_hid() + self._init_matrix() for module in self.modules: try: @@ -415,8 +417,6 @@ class KMKKeyboard: if self.debug_enabled: print('Failed to load extension', err, ext) - self._init_matrix() - self._print_debug_cycle(init=True) def _main_loop(self): @@ -432,17 +432,11 @@ class KMKKeyboard: self.after_matrix_scan() if self.secondary_matrix_update: - # bytearray constructor here to produce a copy - # otherwise things get strange when self.secondary_matrix_update - # gets modified. - self.matrix_update_queue.append(bytearray(self.secondary_matrix_update)) + self.matrix_update_queue.append(self.secondary_matrix_update) self.secondary_matrix_update = None if self.matrix_update: - # bytearray constructor here to produce a copy - # otherwise things get strange when self.matrix_update - # gets modified. - self.matrix_update_queue.append(bytearray(self.matrix_update)) + self.matrix_update_queue.append(self.matrix_update) self.matrix_update = None # only handle one key per cycle. diff --git a/kmk/matrix.py b/kmk/matrix.py index 48c45a9..b5daa65 100644 --- a/kmk/matrix.py +++ b/kmk/matrix.py @@ -1,8 +1,8 @@ import digitalio -def intify_coordinate(row, col): - return row << 8 | col +def intify_coordinate(row, col, len_cols): + return len_cols * row + col class DiodeOrientation: @@ -20,6 +20,12 @@ class DiodeOrientation: ROW2COL = ROWS +class KeyEvent: + def __init__(self, key_number, pressed): + self.key_number = key_number + self.pressed = pressed + + class MatrixScanner: def __init__( self, @@ -27,9 +33,11 @@ class MatrixScanner: rows, diode_orientation=DiodeOrientation.COLUMNS, rollover_cols_every_rows=None, + offset=0, ): self.len_cols = len(cols) self.len_rows = len(rows) + self.offset = offset # A pin cannot be both a row and column, detect this by combining the # two tuples into a set and validating that the length did not drop @@ -92,7 +100,6 @@ class MatrixScanner: self.len_state_arrays = self.len_cols * self.len_rows self.state = bytearray(self.len_state_arrays) - self.report = bytearray(3) def scan_for_changes(self): ''' @@ -131,13 +138,13 @@ class MatrixScanner: iidx // self.rollover_cols_every_rows ) - self.report[0] = new_iidx - self.report[1] = new_oidx + row = new_iidx + col = new_oidx else: - self.report[0] = oidx - self.report[1] = iidx + row = oidx + col = iidx - self.report[2] = new_val + pressed = new_val self.state[ba_idx] = new_val any_changed = True @@ -150,4 +157,5 @@ class MatrixScanner: break if any_changed: - return self.report + key_number = self.len_cols * row + col + self.offset + return KeyEvent(key_number, pressed) diff --git a/kmk/modules/split.py b/kmk/modules/split.py index d5e5033..7281366 100644 --- a/kmk/modules/split.py +++ b/kmk/modules/split.py @@ -6,7 +6,7 @@ from supervisor import runtime, ticks_ms from storage import getmount from kmk.kmktime import check_deadline -from kmk.matrix import intify_coordinate +from kmk.matrix import KeyEvent, intify_coordinate from kmk.modules import Module @@ -119,7 +119,8 @@ class Split(Module): if self.split_flip and self.split_side == SplitSide.RIGHT: keyboard.col_pins = list(reversed(keyboard.col_pins)) - self.split_offset = len(keyboard.col_pins) + if self.split_offset is None: + self.split_offset = len(keyboard.col_pins) * len(keyboard.row_pins) if self.split_type == SplitType.UART and self.data_pin is not None: if self._is_target or not self.uart_flip: @@ -141,12 +142,20 @@ class Split(Module): if not keyboard.coord_mapping: keyboard.coord_mapping = [] - rows_to_calc = len(keyboard.row_pins) * 2 - cols_to_calc = len(keyboard.col_pins) * 2 + rows_to_calc = len(keyboard.row_pins) + cols_to_calc = len(keyboard.col_pins) for ridx in range(rows_to_calc): for cidx in range(cols_to_calc): - keyboard.coord_mapping.append(intify_coordinate(ridx, cidx)) + keyboard.coord_mapping.append( + intify_coordinate(ridx, cidx, cols_to_calc) + ) + for cidx in range(cols_to_calc): + keyboard.coord_mapping.append( + intify_coordinate(rows_to_calc + ridx, cidx, cols_to_calc) + ) + if self.split_side == SplitSide.RIGHT: + keyboard.matrix.offset = self.split_offset def before_matrix_scan(self, keyboard): if self.split_type == SplitType.BLE: @@ -269,12 +278,20 @@ class Split(Module): '''Resets the rescan timer''' self._ble_last_scan = ticks_ms() + def _serialize_update(self, update): + buffer = bytearray(2) + buffer[0] = update.key_number + buffer[1] = update.pressed + return buffer + + def _deserialize_update(self, update): + kevent = KeyEvent(key_number=update[0], pressed=update[1]) + return kevent + def _send_ble(self, update): if self._uart: try: - if not self._is_target: - update[1] += self.split_offset - self._uart.write(update) + self._uart.write(self._serialize_update(update)) except OSError: try: self._uart.disconnect() @@ -289,11 +306,11 @@ class Split(Module): def _receive_ble(self, keyboard): if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer: - while self._uart.in_waiting >= 3: - self._uart_buffer.append(self._uart.read(3)) + while self._uart.in_waiting >= 2: + update = self._deserialize_update(self._uart.read(2)) + self._uart_buffer.append(update) if self._uart_buffer: - keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0)) - return + keyboard.secondary_matrix_update = self._uart_buffer.pop(0) def _checksum(self, update): checksum = bytes([sum(update) & 0xFF]) @@ -303,12 +320,8 @@ class Split(Module): def _send_uart(self, update): # Change offsets depending on where the data is going to match the correct # matrix location of the receiever - - if self.split_side == SplitSide.RIGHT: - # if we're on the right, we by definition are sending to the left, so we need to offset. - update[1] += self.split_offset - if self._uart is not None: + update = self._serialize_update(update) self._uart.write(self.uart_header) self._uart.write(update) self._uart.write(self._checksum(update)) @@ -321,16 +334,13 @@ class Split(Module): microcontroller.reset() - while self._uart.in_waiting >= 5: + while self._uart.in_waiting >= 4: # Check the header if self._uart.read(1) == self.uart_header: - update = self._uart.read(3) + update = self._uart.read(2) # check the checksum if self._checksum(update) == self._uart.read(1): - self._uart_buffer.append(update) - + self._uart_buffer.append(self._deserialize_update(update)) if self._uart_buffer: - keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0)) - - return + keyboard.secondary_matrix_update = self._uart_buffer.pop(0) diff --git a/kmk/modules/tapdance.py b/kmk/modules/tapdance.py index 2bf5274..859a62d 100644 --- a/kmk/modules/tapdance.py +++ b/kmk/modules/tapdance.py @@ -51,7 +51,7 @@ class TapDance(Module): keyboard.hid_pending = True keyboard._send_hid() keyboard.set_timeout( - False, lambda: keyboard.process_key(key, is_pressed, None, None) + False, lambda: keyboard.process_key(key, is_pressed) ) return None