diff --git a/keyboard.go b/keyboard.go index e6ab636..024d4ab 100644 --- a/keyboard.go +++ b/keyboard.go @@ -3,6 +3,7 @@ package keyboard import ( + "bytes" "context" "machine" k "machine/usb/hid/keyboard" @@ -18,6 +19,7 @@ type Device struct { Keyboard UpDowner Mouse Mouser Override [][]Keycode + Macros [2048]byte Debug bool flashCh chan bool flashCnt int @@ -43,6 +45,7 @@ type KBer interface { type UpDowner interface { Up(c k.Keycode) error Down(c k.Keycode) error + Write(b []byte) (n int, err error) } type State uint8 @@ -97,7 +100,7 @@ func (d *Device) Init() error { keys := d.GetMaxKeyCount() // TODO: refactor - rbuf := make([]byte, 4+layers*keyboards*keys*2) + rbuf := make([]byte, 4+layers*keyboards*keys*2+len(device.Macros)) _, err := machine.Flash.ReadAt(rbuf, 0) if err != nil { return err @@ -120,6 +123,14 @@ func (d *Device) Init() error { } } + for i, b := range rbuf[offset:] { + if b == 0xFF { + b = 0 + } + device.Macros[i] = b + } + //copy(device.Macros[:], rbuf[offset:]) + return nil } @@ -141,7 +152,7 @@ func (d *Device) Tick() error { case <-d.flashCh: d.flashCnt = 1 default: - if d.flashCnt >= 500 { + if d.flashCnt >= 5000 { d.flashCnt = 0 err := Save() if err != nil { @@ -200,6 +211,9 @@ func (d *Device) Tick() error { } else if x == keycodes.KeyRestoreDefaultKeymap { // restore default keymap for QMK machine.Flash.EraseBlocks(0, 1) + } else if x&0xFF00 == keycodes.TypeMacroKey { + no := uint8(x & 0x00FF) + d.RunMacro(no) } else if x&0xF000 == 0xD000 { switch x & 0x00FF { case 0x01, 0x02, 0x04, 0x08, 0x10: @@ -269,6 +283,54 @@ func (d *Device) Tick() error { return nil } +func (d *Device) RunMacro(no uint8) error { + macros := bytes.SplitN(d.Macros[:], []byte{0x00}, 16) + + macro := macros[no] + + for i := 0; i < len(macro); { + if macro[i] == 0x01 { + p := macro[i:] + if p[1] == 0x04 { + // delayMs + delayMs := int(p[2]) + int(p[3]-1)*255 + time.Sleep(time.Duration(delayMs) * time.Millisecond) + i += 4 + } else { + kc := keycodeViaToTGK(Keycode(p[2])) + sz := 3 + if p[1] > 0x04 { + kc = Keycode(p[2]) + Keycode(p[3])<<8 + sz += 1 + } + i += sz + kc = keycodeViaToTGK(kc) + + switch p[1] { + case 0x01, 0x05: + k.Keyboard.Down(k.Keycode(kc)) + k.Keyboard.Up(k.Keycode(kc)) + case 0x02, 0x06: + k.Keyboard.Down(k.Keycode(kc)) + case 0x03, 0x07: + k.Keyboard.Up(k.Keycode(kc)) + } + } + } else { + idx := bytes.Index(macro[i:], []byte{0x01}) + if idx == -1 { + idx = len(macro) + } else { + idx = i + idx + } + k.Keyboard.Write(macro[i:idx]) + i = idx + } + } + + return nil +} + func encKey(kb, layer, index int) uint32 { return (uint32(kb) << 24) | (uint32(layer) << 16) | uint32(index) } @@ -348,7 +410,11 @@ func (d *Device) KeyVia(layer, kbIndex, index int) Keycode { // restore default keymap for QMK kc = keycodes.KeyRestoreDefaultKeymap default: - kc = kc & 0x0FFF + if kc&0xFF00 == keycodes.TypeMacroKey { + // skip + } else { + kc = kc & 0x0FFF + } } return kc } @@ -365,6 +431,12 @@ func (d *Device) SetKeycodeVia(layer, kbIndex, index int, key Keycode) { return } //fmt.Printf("SetKeycodeVia(%d, %d, %d, %04X)\n", layer, kbIndex, index, key) + kc := keycodeViaToTGK(key) + + d.kb[kbIndex].SetKeycode(layer, index, kc) +} + +func keycodeViaToTGK(key Keycode) Keycode { kc := key | 0xF000 switch key { @@ -395,9 +467,11 @@ func (d *Device) SetKeycodeVia(layer, kbIndex, index int, key Keycode) { case keycodes.KeyRestoreDefaultKeymap: kc = keycodes.KeyRestoreDefaultKeymap default: + if key&0xFF00 == keycodes.TypeMacroKey { + kc = key + } } - - d.kb[kbIndex].SetKeycode(layer, index, kc) + return kc } func (d *Device) Layer() int { @@ -468,6 +542,10 @@ func (k *Keyboard) Down(c k.Keycode) error { return nil } +func (k *Keyboard) Write(b []byte) (n int, err error) { + return k.Port.Write(b) +} + // UartTxKeyboard is a keyboard that simply sends row/col corresponding to key // placement via UART. For instructions on how to set it up, see bellow. // @@ -506,3 +584,7 @@ func (k *UartTxKeyboard) Down(c k.Keycode) error { } return nil } + +func (k *UartTxKeyboard) Write(b []byte) (n int, err error) { + return len(b), nil +} diff --git a/keycodes/keycodes.go b/keycodes/keycodes.go index 5d5b735..d4563ea 100644 --- a/keycodes/keycodes.go +++ b/keycodes/keycodes.go @@ -11,6 +11,7 @@ const ( TypeMouse = 0xD000 TypeModKey = 0xFF00 TypeToKey = 0xFF10 + TypeMacroKey = 0x7700 ) const ( @@ -41,6 +42,25 @@ const ( KeyTo5 = TypeToKey | 0x05 ) +const ( + KeyMacro0 = TypeMacroKey | 0x00 + KeyMacro1 = TypeMacroKey | 0x01 + KeyMacro2 = TypeMacroKey | 0x02 + KeyMacro3 = TypeMacroKey | 0x03 + KeyMacro4 = TypeMacroKey | 0x04 + KeyMacro5 = TypeMacroKey | 0x05 + KeyMacro6 = TypeMacroKey | 0x06 + KeyMacro7 = TypeMacroKey | 0x07 + KeyMacro8 = TypeMacroKey | 0x08 + KeyMacro9 = TypeMacroKey | 0x09 + KeyMacro10 = TypeMacroKey | 0x0a + KeyMacro11 = TypeMacroKey | 0x0b + KeyMacro12 = TypeMacroKey | 0x0c + KeyMacro13 = TypeMacroKey | 0x0d + KeyMacro14 = TypeMacroKey | 0x0e + KeyMacro15 = TypeMacroKey | 0x0f +) + const ( // restore default keymap for QMK KeyRestoreDefaultKeymap = 0x7C03 diff --git a/via.go b/via.go index f916c4c..08c2214 100644 --- a/via.go +++ b/via.go @@ -158,13 +158,23 @@ func rxHandler2(b []byte) bool { case 0x0D: // DynamicKeymapMacroGetBufferSizeCommand - txb[1] = 0x07 - txb[2] = 0x9B + sz := len(device.Macros) + txb[1] = byte(sz >> 8) + txb[2] = byte(sz) case 0x0C: // DynamicKeymapMacroGetCountCommand txb[1] = 0x10 case 0x0E: // DynamicKeymapMacroGetBufferCommand + offset := (uint16(b[1]) << 8) + uint16(b[2]) + sz := b[3] + copy(txb[4:4+sz], device.Macros[offset:]) + case 0x0F: + // CMD_VIA_MACRO_SET_BUFFER + offset := (uint16(b[1]) << 8) + uint16(b[2]) + sz := b[3] + copy(device.Macros[offset:], txb[4:4+sz]) + device.flashCh <- true case 0x02: // id_get_keyboard_value Changed = false @@ -258,7 +268,7 @@ func Save() error { keyboards := len(device.kb) cnt := device.GetMaxKeyCount() - wbuf := make([]byte, 4+layers*keyboards*cnt*2) + wbuf := make([]byte, 4+layers*keyboards*cnt*2+len(device.Macros)) needed := int64(len(wbuf)) / machine.Flash.EraseBlockSize() if needed == 0 { needed = 1 @@ -287,6 +297,8 @@ func Save() error { } } + copy(wbuf[offset:], device.Macros[:]) + _, err = machine.Flash.WriteAt(wbuf[:], 0) if err != nil { return err