Fix a bug in releasing fn-layer shifted keys.

This commit is contained in:
Phil Hagelberg 2020-02-20 19:12:46 -08:00
parent 66f01f2fa2
commit dcc363073b
6 changed files with 64 additions and 28 deletions

View file

@ -16,7 +16,7 @@ test: ; racket test.rkt
clean: ; -rm -f $(TARGET){,.hex} *.o *.elf *.s
count: ; cloc menelaus.scm keycodes.scm
count: ; cloc menelaus.scm keycodes.scm layout.scm
$(TARGET).hex: $(TARGET).elf
avr-size $(TARGET).elf

View file

@ -49,6 +49,9 @@ into Racket and simulates the GPIO functions with a test harness:
If you hold down two keys which contain a modifier (for instance,
shift and !) and release one of them, it will count as if both are released.
The reset function has no effect; hard-reset must be used to reflash
the firmware.
## License
Copyright © 2014-2019 Phil Hagelberg and contributors

View file

@ -1,5 +1,7 @@
;;; this is the multidvorak layout
;; it will work for the 44-key Atreus 2 or the 42-key Atreus 1.
;; we have to declare this up front and set it later because of circularity
(define layers #f)
(define current-layer #f)
@ -10,15 +12,22 @@
(define (set-layer n)
(lambda (_) (set! current-layer (vector-ref layers n))))
(define (reset _) (call-c-func "reset"))
(define (reset _) (call-c-func "reset")) ; broken
;; on the Atreus 1, we need to expose backtick on the fn layer, but on
;; the Atreus 2 it has its own key, so we put percent there instead
(define backtick-or-percent
key-backtick
;; (sft key-5)
)
;;;; layers
(define base-layer
(vector key-q key-w key-e key-r key-t key-backslash
(vector key-q key-w key-e key-r key-t key-backtick
key-y key-u key-i key-o key-p
key-a key-s key-d key-f key-g key-backtick
key-a key-s key-d key-f key-g key-backslash
key-h key-j key-k key-l key-semicolon
key-z key-x key-c key-v key-b mod-ctrl
@ -28,14 +37,14 @@
key-space fn key-quote key-left-bracket key-enter))
(define fn-layer
(vector (sft key-1) (sft key-2) key-up (sft key-dash) (sft key-equal) 0
key-page-up key-7 key-8 key-9 (sft key-8)
(vector (sft key-1) (sft key-2) key-up (sft key-4) backtick-or-percent (sft key-6)
key-page-up key-7 key-8 key-9 key-backspace
(sft key-3) key-left key-down key-right (sft key-4) 0
key-page-down key-4 key-5 key-6 (sft key-right-bracket)
(sft key-9) key-left key-down key-right (sft key-0) (sft key-7)
key-page-down key-4 key-5 key-6 key-backslash
key-dash key-equal (sft key-9) (sft key-0) (sft key-7) mod-ctrl
key-backtick key-1 key-2 key-3 key-backslash
key-dash key-equal (sft key-3) (sft key-dash) (sft key-equal) mod-ctrl
(sft key-8) key-1 key-2 key-3 (sft key-right-bracket)
(set-layer 2) key-insert mod-super mod-shift key-backspace mod-alt
key-space fn key-e key-0 key-right-bracket))
@ -67,8 +76,8 @@
key-space fn key-quote key-left-bracket key-enter))
(define hard-dvorak-fn-layer
(vector (sft key-1) (sft key-2) key-up (sft key-left-bracket) (sft key-right-bracket) 0
key-page-up key-7 key-8 key-9 (sft key-8)
(vector (sft key-1) (sft key-2) key-up (sft key-4) (sft key-5) (sft key-6)
key-page-up key-7 key-8 key-9 (sft key-backspace)
(sft key-3) key-left key-down key-right (sft key-4) 0
key-page-down key-4 key-5 key-6 (sft key-equal)

View file

@ -1,5 +1,4 @@
(include "keycodes.scm")
(include "layout.scm")
(define rows (list 0 1 2 3))
(define row-pins (vector 3 2 1 0))
@ -8,6 +7,13 @@
(define max-keys 10) ; single USB frame can only send 6 keycodes plus modifiers
;; pcbdown flip, comment out for normal
;; (begin (set! mod-alt (modify 1))
;; (set! mod-ctrl (modify 3))
;; (set! column-pins (vector 11 12 18 19 10 4 7 8 9 5 6)))
(include "layout.scm")
;;;;;;;;;;;;;;;;;;; utils
(define (member v lst)
@ -59,7 +65,7 @@
;;;;;;;;;;;;;;;;;;; debouncing
(define debounce-passes 4)
(define debounce-passes 3)
(define (debounce-matrix-aux last-scan passes-left)
(if (< 0 passes-left)
@ -74,10 +80,10 @@
;;;;;;;;;;;;;;;;;;; press and release tracking
(define last-keys-down (vector 0 0 0 0 0 0 0 0 0 0))
(define last-keys-down (vector #f #f #f #f #f #f #f #f #f #f))
(define (add-last-down-aux key n)
(if (= 0 (vector-ref last-keys-down n))
(if (not (vector-ref last-keys-down n))
(vector-set! last-keys-down n key)
(if (< n 9)
(add-last-down-aux key (+ n 1))
@ -87,8 +93,8 @@
(define (remove-last-down-aux key n)
(if (< n 9)
(if (= key (vector-ref last-keys-down n))
(vector-set! last-keys-down n 0)
(if (= key (or (vector-ref last-keys-down n) -1))
(vector-set! last-keys-down n #f)
(remove-last-down-aux key (+ n 1)))
#f))
@ -98,7 +104,7 @@
(define (remove-aux v lst checked all?)
(if (null? lst)
(reverse checked)
(if (= v (car lst))
(if (equal? v (car lst))
(if all?
(remove-aux v (cdr lst) checked all?)
(reverse (append (cdr lst) checked)))
@ -117,7 +123,7 @@
(define (press/release-for keys-scanned)
(let ((p/r (press/release-aux (list)
(remove-all 0 (vector->list last-keys-down))
(remove-all #f (vector->list last-keys-down))
keys-scanned)))
;; save off press/release into last-keys-down for next cycle
(for-each add-last-down (car p/r))
@ -139,8 +145,6 @@
(define (press-modifier keycode key)
(vector-set! modifiers (- keycode 1) 1)
;; TODO: there is one bug here: if multiple keys have caused a modifier to be
;; active, then releasing only one of the keys will release the modifier.
(vector-set! keys-for-modifiers (- keycode 1) key))
(define (release-modifier keycode key n)
@ -169,17 +173,21 @@
(press-normal-key keycode key)))))
(define (release-key key)
;; lookup here looks it up in the current layer, even if it was pressed in
;; the momentary layer. these need to be consistent across layers or tracked
;; in a similar manner as keys-for-frame.
(let ((keycode (lookup key)))
(if (procedure? keycode)
(keycode #f)
(let ((slot (find keys-for-frame key)))
(let ((slot (find keys-for-frame key))
(modifier-slot (find keys-for-modifiers key)))
(if slot
(begin
(vector-set! keycodes-down slot 0)
(vector-set! keys-for-frame slot 0))
#f)
(if (modifier? keycode)
(release-modifier (unmodify keycode) key 0)
(if modifier-slot
(release-modifier modifier-slot key 0)
#f)))))
;;;;;;;;;;;;;;;;;;; showtime
@ -203,7 +211,7 @@
(define (usb-send m k0 k1 k2 k3 k4 k5)
;; call-c-func is a special form and cannot be applied
(let ((mods (+ (vector-ref m 0) (* (vector-ref m 1) 2)))) ; plus isn't variadic
(let ((mods (+ (vector-ref m 0) (* (vector-ref m 1) 2)))) ; + isn't variadic
(let ((mods (+ mods (+ (* (vector-ref m 2) 4) (* (vector-ref m 3) 8)))))
(call-c-func "usb_send" mods k0 k1 k2 k3 k4 k5))))

View file

@ -59,8 +59,10 @@
((3) . (() ,key-r))
;; another single key
((2) . (() ,key-e))
;; the first key in the whole layout
((0) . (() ,key-q))
;; multiple normal keys
((2 3) . (() ,key-r ,key-e))
((2 3) . (() ,key-e ,key-r))
;; modifier keys (ctrl)
((27) . ((ctrl)))
;; two modifiers (shift+ctrl) get ORed together
@ -77,6 +79,18 @@
((40 35 2) . ((super) ,key-up))
;; releasing fn should leave the previously-pressed key on the fn layer!!!
((2) . (() ,key-up))
;; fn key alone
((40) . (()))
;; fn key and *
((40 28) . ((shift) ,key-8))
;; fn is released
((28) . ((shift) ,key-8))
;; * is released
(() . (()))
;; normal key doesn't leave shift down
((0) . (() ,key-q))
;; changing to L2 (fn+esc)
((40) . (()))
((40 33) . (()))

View file

@ -26,6 +26,7 @@
#define USB_SERIAL_PRIVATE_INCLUDE
#include "usb_keyboard.h"
#include <util/delay.h>
/**************************************************************************
*
@ -603,9 +604,10 @@ ISR(USB_COM_vect)
UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
}
// this fails to enter the bootloader
void reset(void) {
UDCON = 1; USBCON = (1<<FRZCLK); UCSR1B = 0;
// _delay_ms(5);
_delay_ms(5);
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;