Support fn layer and arbitrary functions in layouts.
There is still a bug when you release the fn key but still have another key held down, along with a failing test case.
This commit is contained in:
parent
66406219ac
commit
6fff51cc5f
5 changed files with 137 additions and 34 deletions
7
Makefile
7
Makefile
|
@ -14,8 +14,9 @@ upload: $(TARGET).hex
|
||||||
|
|
||||||
test: ; racket test.rkt
|
test: ; racket test.rkt
|
||||||
|
|
||||||
clean:
|
clean: ; -rm -f $(TARGET){,.hex} *.o *.elf *.s
|
||||||
-rm -f $(TARGET){,.hex} *.o *.elf *.s
|
|
||||||
|
count: ; cloc *.scm
|
||||||
|
|
||||||
$(TARGET).hex: $(TARGET).elf
|
$(TARGET).hex: $(TARGET).elf
|
||||||
avr-size $(TARGET).elf
|
avr-size $(TARGET).elf
|
||||||
|
@ -31,4 +32,4 @@ usb_keyboard.s: usb_keyboard.h usb_keyboard.c
|
||||||
avr-gcc -std=gnu99 -S -D F_CPU=$(F_CPU)UL -mmcu=$(MCU) -c \
|
avr-gcc -std=gnu99 -S -D F_CPU=$(F_CPU)UL -mmcu=$(MCU) -c \
|
||||||
-o usb_keyboard.s usb_keyboard.c
|
-o usb_keyboard.s usb_keyboard.c
|
||||||
|
|
||||||
.PHONY: build upload test clean
|
.PHONY: build upload test clean count
|
||||||
|
|
37
keycodes.scm
37
keycodes.scm
|
@ -26,13 +26,38 @@
|
||||||
(define key-x 27)
|
(define key-x 27)
|
||||||
(define key-y 28)
|
(define key-y 28)
|
||||||
(define key-z 29)
|
(define key-z 29)
|
||||||
(define key-semicolon 51)
|
|
||||||
|
|
||||||
|
(define key-1 30)
|
||||||
|
(define key-2 31)
|
||||||
|
(define key-3 32)
|
||||||
|
(define key-4 33)
|
||||||
|
(define key-5 34)
|
||||||
|
(define key-6 35)
|
||||||
|
(define key-7 36)
|
||||||
|
(define key-8 37)
|
||||||
|
(define key-9 38)
|
||||||
|
(define key-0 39)
|
||||||
|
|
||||||
|
(define key-up 82)
|
||||||
|
(define key-down 81)
|
||||||
|
(define key-left 80)
|
||||||
|
(define key-right 79)
|
||||||
|
|
||||||
|
(define key-page-up 75)
|
||||||
|
(define key-page-down 78)
|
||||||
|
(define key-home 74)
|
||||||
|
(define key-end 77)
|
||||||
|
(define key-insert 73)
|
||||||
|
|
||||||
|
(define key-semicolon 51)
|
||||||
(define key-comma 54)
|
(define key-comma 54)
|
||||||
(define key-period 55)
|
(define key-period 55)
|
||||||
(define key-slash 56)
|
(define key-slash 56)
|
||||||
(define key-dash 45)
|
(define key-dash 45)
|
||||||
(define key-quote 52)
|
(define key-quote 52)
|
||||||
|
(define key-equal 46)
|
||||||
|
(define key-left-bracket 47)
|
||||||
|
(define key-right-bracket 48)
|
||||||
|
|
||||||
(define key-space 44)
|
(define key-space 44)
|
||||||
(define key-backspace 42)
|
(define key-backspace 42)
|
||||||
|
@ -43,12 +68,18 @@
|
||||||
(define key-backslash 49)
|
(define key-backslash 49)
|
||||||
(define key-backtick 53)
|
(define key-backtick 53)
|
||||||
|
|
||||||
|
(define key-vol-up 128)
|
||||||
|
(define key-vol-down 129)
|
||||||
|
|
||||||
(define (modifier? keycode) (list? keycode))
|
(define (modifier? keycode) (list? keycode))
|
||||||
(define (modify keycode) (list keycode))
|
(define (modify keycode) (list keycode))
|
||||||
(define (unmodify keycode) (car keycode))
|
(define (unmodify keycode) (car keycode))
|
||||||
|
|
||||||
|
;; currently you can only combo with one modifier and one normal key
|
||||||
|
(define (combo modifier keycode) (list (car modifier) keycode))
|
||||||
|
(define (uncombo keycode) (and (= 2 (length keycode)) (car (cdr keycode))))
|
||||||
|
|
||||||
(define mod-ctrl (modify #x01))
|
(define mod-ctrl (modify #x01))
|
||||||
(define mod-shift (modify #x02))
|
(define mod-shift (modify #x02))
|
||||||
(define mod-alt (modify #x04))
|
(define mod-alt (modify #x04))
|
||||||
(define mod-gui (modify #x08))
|
(define mod-super (modify #x08))
|
||||||
(define mod-fn (modify #x16))
|
|
||||||
|
|
56
layout.scm
56
layout.scm
|
@ -1,12 +1,50 @@
|
||||||
(define layout
|
;;; this is the multidvorak layout
|
||||||
(vector key-q key-w key-e key-r key-t key-backslash
|
|
||||||
key-y key-u key-i key-o key-p
|
|
||||||
|
|
||||||
key-a key-s key-d key-f key-g key-backtick
|
;; we have to declare this up front and set it later because of circularity
|
||||||
key-h key-j key-k key-l key-semicolon
|
(define layers (vector #f #f #f))
|
||||||
|
(define current-layer #f)
|
||||||
|
(define momentary-layer #f)
|
||||||
|
|
||||||
key-z key-x key-c key-v key-b mod-alt
|
(define (fn)
|
||||||
key-n key-m key-comma key-period key-slash
|
(set! momentary-layer (vector-ref layers 1)))
|
||||||
|
|
||||||
key-esc key-tab mod-gui mod-shift key-backspace mod-ctrl
|
(define (set-layer-2)
|
||||||
key-space mod-fn key-dash key-quote key-enter))
|
(set! current-layer (vector-ref layers 2)))
|
||||||
|
|
||||||
|
(define (set-layer-0)
|
||||||
|
(set! current-layer (vector-ref layers 0)))
|
||||||
|
|
||||||
|
(vector-set!
|
||||||
|
layers 0
|
||||||
|
(vector key-q key-w key-e key-r key-t key-backslash
|
||||||
|
key-y key-u key-i key-o key-p
|
||||||
|
|
||||||
|
key-a key-s key-d key-f key-g key-backtick
|
||||||
|
key-h key-j key-k key-l key-semicolon
|
||||||
|
|
||||||
|
key-z key-x key-c key-v key-b mod-alt
|
||||||
|
key-n key-m key-comma key-period key-slash
|
||||||
|
|
||||||
|
key-esc key-tab mod-super mod-shift key-backspace mod-ctrl
|
||||||
|
key-space fn key-quote key-right-bracket key-enter))
|
||||||
|
|
||||||
|
(vector-set!
|
||||||
|
layers 1
|
||||||
|
(vector (combo mod-shift key-1) (combo mod-shift key-2) key-up
|
||||||
|
(combo mod-shift key-dash) (combo mod-shift key-equal)
|
||||||
|
0 key-page-up key-7 key-8 key-9 (combo mod-shift key-8)
|
||||||
|
|
||||||
|
(combo mod-shift key-3) key-left key-down key-right
|
||||||
|
(combo mod-shift key-4) 0
|
||||||
|
key-page-down key-4 key-5 key-6 (combo mod-shift key-right-bracket)
|
||||||
|
|
||||||
|
key-dash key-equal (combo mod-shift key-9)
|
||||||
|
(combo mod-shift key-0) (combo mod-shift key-7) mod-alt
|
||||||
|
key-backtick key-1 key-2 key-3 key-backslash
|
||||||
|
|
||||||
|
set-layer-2 key-insert mod-super mod-shift key-backspace mod-ctrl
|
||||||
|
key-space fn key-dash key-e key-0 key-right-bracket))
|
||||||
|
|
||||||
|
(vector-set!
|
||||||
|
layers 2 ; TODO
|
||||||
|
(vector 0))
|
||||||
|
|
37
menelaus.scm
37
menelaus.scm
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
(define max-keys 6) ; a single USB frame can only send 6 keycodes plus modifiers
|
(define max-keys 6) ; a single USB frame can only send 6 keycodes plus modifiers
|
||||||
|
|
||||||
;;; matrix
|
;;;;;;;;;;;;;;;;;;; matrix
|
||||||
|
|
||||||
(define (offset-for row col)
|
(define (offset-for row col)
|
||||||
(+ col (* row (length columns))))
|
(+ col (* row (length columns))))
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
(car rows-left) columns)))
|
(car rows-left) columns)))
|
||||||
(scan-matrix keys-pressed key-count (cdr rows-left)))))
|
(scan-matrix keys-pressed key-count (cdr rows-left)))))
|
||||||
|
|
||||||
;;; debouncing
|
;;;;;;;;;;;;;;;;;;; debouncing
|
||||||
|
|
||||||
(define this-scan (vector 0 0 0 0 0 0 0))
|
(define this-scan (vector 0 0 0 0 0 0 0))
|
||||||
(define last-scan (vector 0 0 0 0 0 0 0))
|
(define last-scan (vector 0 0 0 0 0 0 0))
|
||||||
|
@ -50,29 +50,46 @@
|
||||||
(define debounce-passes 8)
|
(define debounce-passes 8)
|
||||||
|
|
||||||
(define (debounce-matrix keys-pressed last-count passes-left)
|
(define (debounce-matrix keys-pressed last-count passes-left)
|
||||||
(vector-copy this-scan last-scan 0 6 0)
|
;; older versions of microscheme don't have vector-copy!, only vector-copy
|
||||||
|
;; which does the same thing but takes the arguments in a different order
|
||||||
|
(vector-copy! last-scan 0 this-scan 0 6)
|
||||||
(if (< 0 passes-left)
|
(if (< 0 passes-left)
|
||||||
(let ((this-count (scan-matrix this-scan 1 rows)))
|
(let ((this-count (scan-matrix this-scan 1 rows)))
|
||||||
(if (and (= this-count last-count)
|
(if (and (= this-count last-count)
|
||||||
(equal? this-scan last-scan))
|
(equal? this-scan last-scan))
|
||||||
(debounce-matrix keys-pressed this-count (- passes-left 1))
|
(debounce-matrix keys-pressed this-count (- passes-left 1))
|
||||||
(debounce-matrix keys-pressed this-count passes-left)))
|
(debounce-matrix keys-pressed this-count passes-left)))
|
||||||
(begin (vector-copy this-scan keys-pressed 0 6 0)
|
(begin (vector-copy! keys-pressed 0 this-scan 0 6)
|
||||||
last-count)))
|
last-count)))
|
||||||
|
|
||||||
;;; layout
|
;;;;;;;;;;;;;;;;;;; layout
|
||||||
|
|
||||||
|
(define (lookup keys-pressed which-key)
|
||||||
|
(let ((layout (or momentary-layer current-layer)))
|
||||||
|
(vector-ref layout (vector-ref keys-pressed which-key))))
|
||||||
|
|
||||||
(define (keycode-for keys-pressed which-key keycodes)
|
(define (keycode-for keys-pressed which-key keycodes)
|
||||||
(let ((code (vector-ref layout (vector-ref keys-pressed which-key))))
|
(let ((code (lookup keys-pressed which-key)))
|
||||||
;; (printf "keycode ~s ~s~n" code which-key)
|
;; (printf "keycode ~s ~s~n" code which-key)
|
||||||
(if (modifier? code)
|
(if (modifier? code)
|
||||||
(begin (vector-set! keycodes 0 (+ (vector-ref keycodes 0)
|
(begin (vector-set! keycodes 0 (+ (vector-ref keycodes 0)
|
||||||
(unmodify code)))
|
(unmodify code)))
|
||||||
#f)
|
(uncombo code))
|
||||||
code)))
|
(and (not (procedure? code)) code))))
|
||||||
|
|
||||||
|
(define (call-functions keys-pressed key-count)
|
||||||
|
(if (< 0 key-count)
|
||||||
|
(let ((code (lookup keys-pressed key-count)))
|
||||||
|
(if (procedure? code)
|
||||||
|
(code)
|
||||||
|
#f)
|
||||||
|
(call-functions keys-pressed (- key-count 1)))
|
||||||
|
#f))
|
||||||
|
|
||||||
;; translate key numbers into specific USB keycodes
|
;; translate key numbers into specific USB keycodes
|
||||||
(define (keycodes-for keys-pressed key-count keycodes)
|
(define (keycodes-for keys-pressed key-count keycodes)
|
||||||
|
;; this happens before we look up "regular" keycodes because it changes layers
|
||||||
|
(call-functions keys-pressed key-count)
|
||||||
(if (= 0 key-count)
|
(if (= 0 key-count)
|
||||||
(vector->list keycodes)
|
(vector->list keycodes)
|
||||||
(let ((keycode (keycode-for keys-pressed key-count keycodes)))
|
(let ((keycode (keycode-for keys-pressed key-count keycodes)))
|
||||||
|
@ -81,9 +98,10 @@
|
||||||
#f)
|
#f)
|
||||||
(keycodes-for keys-pressed (- key-count 1) keycodes))))
|
(keycodes-for keys-pressed (- key-count 1) keycodes))))
|
||||||
|
|
||||||
;;; showtime
|
;;;;;;;;;;;;;;;;;;; showtime
|
||||||
|
|
||||||
(define (init)
|
(define (init)
|
||||||
|
(set-layer-0)
|
||||||
(for-each-vector output row-pins)
|
(for-each-vector output row-pins)
|
||||||
(for-each-vector high row-pins)
|
(for-each-vector high row-pins)
|
||||||
(for-each-vector input column-pins)
|
(for-each-vector input column-pins)
|
||||||
|
@ -96,6 +114,7 @@
|
||||||
(call-c-func "usb_send" modifiers key1 key2 key3 key4 key5 key6))
|
(call-c-func "usb_send" modifiers key1 key2 key3 key4 key5 key6))
|
||||||
|
|
||||||
(define (loop)
|
(define (loop)
|
||||||
|
(set! momentary-layer #f)
|
||||||
(free! (let ((keys-pressed (vector 0 0 0 0 0 0 0)))
|
(free! (let ((keys-pressed (vector 0 0 0 0 0 0 0)))
|
||||||
;; scanning the matrix tells us only which physical keys were
|
;; scanning the matrix tells us only which physical keys were
|
||||||
;; pressed and how many; it doesn't tell us which keycodes to
|
;; pressed and how many; it doesn't tell us which keycodes to
|
||||||
|
|
34
test.rkt
34
test.rkt
|
@ -13,13 +13,8 @@
|
||||||
(define (high pin) (vector-set! pins pin #t))
|
(define (high pin) (vector-set! pins pin #t))
|
||||||
(define (low pin) (vector-set! pins pin #f))
|
(define (low pin) (vector-set! pins pin #f))
|
||||||
|
|
||||||
;; microscheme has this as a separate form but it's just for
|
;; microscheme has this as a separate form
|
||||||
(define (for-each-vector f v) (for ([x v]) (f x)))
|
(define for-each-vector vector-map)
|
||||||
|
|
||||||
(define (vector-copy src dest src-start src-finish dest-start)
|
|
||||||
;; ignore src-start and dest-start
|
|
||||||
(for ([i (range src-finish)])
|
|
||||||
(vector-set! dest i (vector-ref src i))))
|
|
||||||
|
|
||||||
(define last-usb-frame #f) ; save this off so we can test it
|
(define last-usb-frame #f) ; save this off so we can test it
|
||||||
|
|
||||||
|
@ -49,12 +44,31 @@
|
||||||
(define (make-test-data)
|
(define (make-test-data)
|
||||||
;; have to put this in a function so we can internal-define; eww
|
;; have to put this in a function so we can internal-define; eww
|
||||||
(include "keycodes.scm")
|
(include "keycodes.scm")
|
||||||
;; pair of pins/keycodes
|
;; each test case is a pair of inputs->outputs
|
||||||
`(((1) . (0 ,key-w 0 0 0 0 0))
|
;; inputs are a list of keys (by offset), outputs are elements of a USB frame
|
||||||
|
`(;; single key
|
||||||
|
((3) . (0 ,key-r 0 0 0 0 0))
|
||||||
|
;; another single key
|
||||||
((2) . (0 ,key-e 0 0 0 0 0))
|
((2) . (0 ,key-e 0 0 0 0 0))
|
||||||
|
;; multiple normal keys
|
||||||
|
((2 3) . (0 ,key-e ,key-r 0 0 0 0))
|
||||||
|
;; modifier keys (alt)
|
||||||
((27) . (4 0 0 0 0 0 0))
|
((27) . (4 0 0 0 0 0 0))
|
||||||
|
;; two modifiers (shift+alt) get ORed together
|
||||||
|
((27 36) . (6 0 0 0 0 0 0))
|
||||||
|
;; modifier (shift) and normal key
|
||||||
((36 4) . (2 ,key-t 0 0 0 0 0))
|
((36 4) . (2 ,key-t 0 0 0 0 0))
|
||||||
((36 4 6) . (2 ,key-t ,key-y 0 0 0 0))))
|
;; modifier and multiple normal keys
|
||||||
|
((36 4 6) . (2 ,key-t ,key-y 0 0 0 0))
|
||||||
|
;; fn key alone
|
||||||
|
((40) . (0 0 0 0 0 0 0))
|
||||||
|
;; fn key and normal key
|
||||||
|
((40 1) . (2 ,key-2 0 0 0 0 0))
|
||||||
|
;; fn key and modifier and normal key
|
||||||
|
((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))
|
||||||
|
))
|
||||||
|
|
||||||
(define test-data (make-test-data))
|
(define test-data (make-test-data))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue