2019-07-02 03:01:10 +00:00
|
|
|
#lang racket
|
|
|
|
|
2019-07-02 05:27:33 +00:00
|
|
|
;; this file simulates the hardware necessary to test the keyboard firmware,
|
|
|
|
;; because doing actual development on an atmega32u4 is nightmarishly tedious.
|
|
|
|
|
2019-07-02 03:01:10 +00:00
|
|
|
(define pins (make-vector 20))
|
|
|
|
(define keys (make-vector 44 #f))
|
|
|
|
|
2019-07-02 05:27:33 +00:00
|
|
|
(define output void) ; don't bother to simulate pin modes
|
2019-07-02 03:01:10 +00:00
|
|
|
(define input void)
|
|
|
|
(define pause void)
|
|
|
|
|
|
|
|
(define (high pin) (vector-set! pins pin #t))
|
|
|
|
(define (low pin) (vector-set! pins pin #f))
|
|
|
|
|
2019-07-03 01:11:04 +00:00
|
|
|
;; microscheme has this as a separate form
|
2020-03-22 17:52:33 +00:00
|
|
|
(define (for-each-vector v f) (vector-map v f) (void))
|
2019-07-02 05:57:30 +00:00
|
|
|
|
2019-07-02 05:27:33 +00:00
|
|
|
(define last-usb-frame #f) ; save this off so we can test it
|
2019-07-02 03:01:10 +00:00
|
|
|
|
2019-07-06 23:49:29 +00:00
|
|
|
(define (mods-list mods)
|
|
|
|
(filter symbol? (list (if (positive? (bitwise-and mods 1)) 'ctrl 0)
|
|
|
|
(if (positive? (bitwise-and mods 2)) 'shift 0)
|
|
|
|
(if (positive? (bitwise-and mods 4)) 'alt 0)
|
2021-12-13 19:41:55 +00:00
|
|
|
(if (positive? (bitwise-and mods 8)) 'super 0)
|
|
|
|
(if (positive? (bitwise-and mods 64)) altgr 0))))
|
2019-07-06 23:49:29 +00:00
|
|
|
|
|
|
|
(define (usb-save mods . args)
|
|
|
|
(set! last-usb-frame (cons (mods-list mods) args)))
|
2019-07-06 02:53:04 +00:00
|
|
|
|
2019-07-02 03:01:10 +00:00
|
|
|
(define (call-c-func f-name . args)
|
2019-07-06 02:53:04 +00:00
|
|
|
(when (equal? f-name "usb_send")
|
|
|
|
(apply usb-save args)))
|
2019-07-02 03:01:10 +00:00
|
|
|
|
|
|
|
(define (active-row)
|
2019-07-02 05:27:33 +00:00
|
|
|
;; hypothetically we could have multiple active rows but we just assume one
|
2019-07-02 03:01:10 +00:00
|
|
|
(for/first ([pin row-pins]
|
|
|
|
[row (range (length rows))]
|
|
|
|
#:when (not (vector-ref pins pin)))
|
|
|
|
row))
|
|
|
|
|
|
|
|
(define (col-for pin)
|
|
|
|
(for/first ([c-pin column-pins]
|
|
|
|
[col (range (length columns))]
|
|
|
|
#:when (= c-pin pin))
|
|
|
|
col))
|
|
|
|
|
|
|
|
(define (low? pin)
|
|
|
|
;; (when (vector-ref keys (offset-for (active-row) (col-for pin)))
|
|
|
|
;; (printf "lookup ~s ~s ~n" pin (offset-for (active-row) (col-for pin)))
|
|
|
|
;; (printf "Keys ~s~n" keys))
|
|
|
|
(vector-ref keys (offset-for (active-row) (col-for pin))))
|
|
|
|
|
|
|
|
(define (make-test-data)
|
|
|
|
;; have to put this in a function so we can internal-define; eww
|
|
|
|
(include "keycodes.scm")
|
2019-07-03 01:11:04 +00:00
|
|
|
;; each test case is a pair of inputs->outputs
|
|
|
|
;; inputs are a list of keys (by offset), outputs are elements of a USB frame
|
|
|
|
`(;; single key
|
2019-07-06 02:53:04 +00:00
|
|
|
((3) . (() ,key-r))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; another single key
|
2019-07-06 02:53:04 +00:00
|
|
|
((2) . (() ,key-e))
|
2020-02-21 03:12:46 +00:00
|
|
|
;; the first key in the whole layout
|
|
|
|
((0) . (() ,key-q))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; multiple normal keys
|
2020-02-21 03:12:46 +00:00
|
|
|
((2 3) . (() ,key-e ,key-r))
|
2019-07-03 01:49:41 +00:00
|
|
|
;; modifier keys (ctrl)
|
2019-07-06 02:53:04 +00:00
|
|
|
((27) . ((ctrl)))
|
2019-07-03 01:49:41 +00:00
|
|
|
;; two modifiers (shift+ctrl) get ORed together
|
2019-07-06 02:53:04 +00:00
|
|
|
((27 36) . ((ctrl shift)))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; modifier (shift) and normal key
|
2019-07-06 02:53:04 +00:00
|
|
|
((36 4) . ((shift) ,key-t))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; modifier and multiple normal keys
|
2019-07-06 02:53:04 +00:00
|
|
|
((36 4 6) . ((shift) ,key-t ,key-y))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; fn key alone
|
2019-07-06 02:53:04 +00:00
|
|
|
((40) . (()))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; fn key and normal key
|
2019-07-06 02:53:04 +00:00
|
|
|
((40 1) . ((shift) ,key-2))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; fn key and modifier and normal key
|
2019-07-06 02:53:04 +00:00
|
|
|
((40 35 2) . ((super) ,key-up))
|
2019-07-03 01:11:04 +00:00
|
|
|
;; releasing fn should leave the previously-pressed key on the fn layer!!!
|
2019-07-06 02:53:04 +00:00
|
|
|
((2) . (() ,key-up))
|
2020-02-21 03:12:46 +00:00
|
|
|
|
|
|
|
;; 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))
|
|
|
|
|
2019-07-04 03:31:25 +00:00
|
|
|
;; changing to L2 (fn+esc)
|
2019-07-06 02:53:04 +00:00
|
|
|
((40) . (()))
|
|
|
|
((40 33) . (()))
|
2019-07-04 03:31:25 +00:00
|
|
|
;; fn+esc should stay on L2 across multiple scans
|
2019-07-06 02:53:04 +00:00
|
|
|
((40 33) . (()))
|
|
|
|
;; release fn to disable momentary
|
|
|
|
(() . (()))
|
2019-07-04 03:31:25 +00:00
|
|
|
;; hitting an L2 key
|
2019-07-06 02:53:04 +00:00
|
|
|
((1) . (() ,key-home))
|
|
|
|
;; L2 two keys and mod
|
|
|
|
((36 39 18) . ((shift) ,key-f4 ,key-space))
|
|
|
|
;; back to base (fn)
|
|
|
|
((40) . (()))
|
2019-07-04 03:31:25 +00:00
|
|
|
;; base layer key
|
2019-07-06 02:53:04 +00:00
|
|
|
((2) . (() ,key-e))
|
2019-07-07 00:03:35 +00:00
|
|
|
;; seven keys down
|
|
|
|
((1 2 3 4 7 8 9) . (() ,key-e ,key-w ,key-r ,key-t ,key-u ,key-i))
|
2019-07-06 02:53:04 +00:00
|
|
|
;; shift combo and shift key simultaneously
|
|
|
|
((40) . (()))
|
|
|
|
((40 1 36) . ((shift) ,key-2))
|
|
|
|
((40 1) . (() ,key-2))
|
|
|
|
((40) . (()))
|
|
|
|
(() . (()))))
|
2019-07-02 03:01:10 +00:00
|
|
|
|
|
|
|
(define test-data (make-test-data))
|
|
|
|
|
2019-07-02 05:27:33 +00:00
|
|
|
(define failures '())
|
2019-07-02 03:01:10 +00:00
|
|
|
|
|
|
|
(define (fail expected actual)
|
2019-07-02 05:27:33 +00:00
|
|
|
(printf "F")
|
|
|
|
(set! failures
|
|
|
|
(cons (format "Expected ~s, got ~s~n" expected actual) failures)))
|
|
|
|
|
|
|
|
(define (finish)
|
2019-07-04 03:31:25 +00:00
|
|
|
(printf (string-join (reverse failures)
|
|
|
|
"~n" #:before-first "~n" #:after-last "~n"))
|
2019-07-02 05:27:33 +00:00
|
|
|
(exit (if (empty? failures) 0 1)))
|
2019-07-02 03:01:10 +00:00
|
|
|
|
|
|
|
;; we can perform our checks here and make changes to the pin state.
|
|
|
|
(define-syntax free!
|
|
|
|
(syntax-rules ()
|
|
|
|
[(free! body) (if (empty? test-data)
|
2019-07-02 05:27:33 +00:00
|
|
|
(finish)
|
2019-07-02 03:01:10 +00:00
|
|
|
(let ([test-case (car test-data)])
|
|
|
|
(for ([i (vector-length keys)])
|
|
|
|
(vector-set! keys i
|
|
|
|
(and (member i (car test-case)) #t)))
|
|
|
|
body
|
2019-07-06 02:53:04 +00:00
|
|
|
(let ((actual (cons (car last-usb-frame)
|
|
|
|
(remove-all
|
|
|
|
0 (cdr last-usb-frame)))))
|
|
|
|
(if (equal? (cdr test-case) actual)
|
|
|
|
(printf ".")
|
|
|
|
(fail (cdr test-case) actual)))
|
2019-07-02 03:01:10 +00:00
|
|
|
(set! test-data (cdr test-data))))]))
|
|
|
|
|
2020-03-22 17:52:33 +00:00
|
|
|
(include "multidvorak.scm")
|