Better layer support; disable L2 for now.

Need press/release tracking before sticky layers will work.
This commit is contained in:
Phil Hagelberg 2019-07-03 20:31:25 -07:00
parent 9a9ddaaa98
commit d2a39a5cc4
5 changed files with 48 additions and 42 deletions

View file

@ -16,13 +16,13 @@ test: ; racket test.rkt
clean: ; -rm -f $(TARGET){,.hex} *.o *.elf *.s
count: ; cloc *.scm
count: ; cloc menelaus.scm keycodes.scm
$(TARGET).hex: $(TARGET).elf
avr-size $(TARGET).elf
avr-objcopy --output-target=ihex $(TARGET).elf $(TARGET).hex
%.s: %.scm
$(TARGET).s: $(TARGET).scm layout.scm keycodes.scm
microscheme -m LEO $(TARGET).scm
%.elf: %.s usb_keyboard.s

View file

@ -11,13 +11,15 @@ A firmware for the
* Multiple layers, momentary and sticky (limited only by memory)
* Combo keys (a single keystroke can send a modifier and a non-modifier)
* Bind arbitrary Scheme functions to a key
* ~255 lines of code
* ~200 lines of code
## Usage
This currently requires Microscheme with the addition of
`vector-copy!` which at the time of this writing is only available on
[this branch](https://github.com/ryansuchocki/microscheme/pull/31).
`vector-copy!` which at the time of this writing is only on the master branch.
Also requires [avrdude](https://www.nongnu.org/avrdude/) for uploading
to the device.
Replace `/dev/ttyACM0` with the path your OS assigns to the USB
bootloader of the microcontroller:
@ -38,6 +40,8 @@ into Racket and simulates the GPIO functions with a test harness:
## Known bugs
Still working out some quirks with sticky layers.
If you hold the fn key, press a button (say Q) and then release fn
without releasing Q, it will send a keycode for Q rather than simply
leaving the previous fn+Q keycodes as held down.

View file

@ -1,29 +1,22 @@
;;; this is the multidvorak layout
;; we have to declare this up front and set it later because of circularity
(define layers (vector #f #f #f))
(define layers #f)
(define current-layer #f)
(define momentary-layer #f)
(define (fn)
(set! momentary-layer (vector-ref layers 1)))
(define (set-layer-2)
(set! current-layer (vector-ref layers 2)))
(define (set-layer-0)
(set! current-layer (vector-ref layers 0)))
(define (set-layer-hard)
(set! current-layer (vector-ref layers 3)))
(define (set-layer n)
(lambda () (set! current-layer (vector-ref layers n))))
(define (reset)
#f) ;; TODO: uh, seriously. I need this. how.
;;;; layers
(vector-set! ; base
layers 0
(define base-layer
(vector key-q key-w key-e key-r key-t key-backslash
key-y key-u key-i key-o key-p
@ -36,8 +29,7 @@
key-esc key-tab mod-super mod-shift key-backspace mod-alt
key-space fn key-quote key-left-bracket key-enter))
(vector-set! ; fn
layers 1
(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)
@ -47,25 +39,25 @@
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
set-layer-2 key-insert mod-super mod-shift key-backspace mod-alt
;; still got some bugs in layering to work out! make this reset for now
reset ;; (set-layer 2)
key-insert mod-super mod-shift key-backspace mod-alt
key-space fn key-e key-0 key-right-bracket))
(vector-set! ; l2 (function keys, etc)
layers 2
(define l2-layer
(vector key-insert key-home key-up key-end key-page-up 0
key-up key-f7 key-f8 key-f9 key-f10
key-delete key-left key-down key-right key-page-down 0
key-down key-f4 key-f5 key-f6 key-f11
0 key-vol-up 0 0 reset mod-ctrl
set-layer-hard key-f1 key-f2 key-f3 key-f12
(set-layer 0) key-vol-up 0 0 reset mod-ctrl
(set-layer 4) key-f1 key-f2 key-f3 key-f12
0 key-vol-down mod-super mod-shift key-backspace mod-alt
key-space set-layer-0 key-printscreen key-scroll-lock key-pause))
key-space 0 key-printscreen key-scroll-lock key-pause))
(vector-set! ; hard dvorak
layers 3
(define hard-dvorak-layer
(vector key-quote key-comma key-period key-p key-y key-backslash
key-f key-g key-c key-r key-l
@ -78,8 +70,7 @@
key-esc key-tab mod-super mod-shift key-backspace mod-alt
key-space fn key-quote key-left-bracket key-enter))
(vector-set! ; hard dvorak fn
layers 4
(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)
@ -89,5 +80,8 @@
key-left-bracket key-right-bracket (sft key-9) (sft key-0) (sft key-7) mod-ctrl
key-backtick key-1 key-2 key-3 key-backslash
set-layer-2 key-insert mod-super mod-shift key-backspace mod-alt
(set-layer 2) key-insert mod-super mod-shift key-backspace mod-alt
key-space fn key-e key-0 key-right-bracket))
(set! layers (vector base-layer fn-layer l2-layer
hard-dvorak-layer hard-dvorak-fn-layer))

View file

@ -16,11 +16,11 @@
(define (scan-key keys-pressed key-count row col)
;; pullup resistors mean a closed circuit is low rather than high
(if (low? (vector-ref column-pins col))
(begin
(if (<= key-count max-keys)
(begin
(vector-set! keys-pressed key-count (offset-for row col))
#f)
(+ key-count 1))
key-count)
key-count))
(define (scan-column keys-pressed key-count row columns-left)
@ -47,7 +47,7 @@
(define this-scan (vector 0 0 0 0 0 0 0))
(define last-scan (vector 0 0 0 0 0 0 0))
(define debounce-passes 8)
(define debounce-passes 4)
(define (debounce-matrix keys-pressed last-count passes-left)
;; older versions of microscheme don't have vector-copy!, only vector-copy
@ -80,9 +80,7 @@
(define (call-functions keys-pressed key-count)
(if (< 0 key-count)
(let ((code (lookup keys-pressed key-count)))
(if (procedure? code)
(code)
#f)
(and (procedure? code) (code))
(call-functions keys-pressed (- key-count 1)))
#f))
@ -93,15 +91,14 @@
(if (= 0 key-count)
(vector->list keycodes)
(let ((keycode (keycode-for keys-pressed key-count keycodes)))
(if keycode
(vector-set! keycodes key-count keycode)
#f)
(and keycode
(vector-set! keycodes key-count keycode))
(keycodes-for keys-pressed (- key-count 1) keycodes))))
;;;;;;;;;;;;;;;;;;; showtime
(define (init)
(set-layer-0)
(set! current-layer (vector-ref layers 0))
(for-each-vector output row-pins)
(for-each-vector high row-pins)
(for-each-vector input column-pins)

View file

@ -68,6 +68,16 @@
((40 35 2) . (8 ,key-up 0 0 0 0 0))
;; releasing fn should leave the previously-pressed key on the fn layer!!!
;; ((2) . (0 ,key-up 0 0 0 0 0))
;; changing to L2 (fn+esc)
((40 33) . (0 0 0 0 0 0 0))
;; fn+esc should stay on L2 across multiple scans
((40 33) . (0 0 0 0 0 0 0))
;; hitting an L2 key
;; ((1) . (0 ,key-home 0 0 0 0 0))
;; back to base (key above esc)
;; ((22) . (0 0 0 0 0 0 0))
;; base layer key
((2) . (0 ,key-e 0 0 0 0 0))
))
(define test-data (make-test-data))
@ -80,7 +90,8 @@
(cons (format "Expected ~s, got ~s~n" expected actual) failures)))
(define (finish)
(printf (string-join failures "~n" #:before-first "~n" #:after-last "~n"))
(printf (string-join (reverse failures)
"~n" #:before-first "~n" #:after-last "~n"))
(exit (if (empty? failures) 0 1)))
;; we can perform our checks here and make changes to the pin state.