diff options
| author | markspanbroek <mark@spanbroek.net> | 2018-10-22 21:37:03 +0200 |
|---|---|---|
| committer | Drashna Jaelre <drashna@live.com> | 2018-10-22 12:37:03 -0700 |
| commit | 6d7745a110daad815fe5edbb35a2e33702f24aaa (patch) | |
| tree | d18512753edbec9668e8b0b4cdf4f688e2a39971 /tmk_core | |
| parent | bf57587e6203e3bcabbc161c1d45b9a6cc7abfaa (diff) | |
| download | qmk_firmware-6d7745a110daad815fe5edbb35a2e33702f24aaa.tar.gz qmk_firmware-6d7745a110daad815fe5edbb35a2e33702f24aaa.zip | |
Keyboard: Port of TMK XT USB Converter (#3619)
* Converter: add XT USB converter from TMK
* Converter: port TMK code for USB converter to QMK
* Apply requested changes after code review by @drashna
- use "pragma once" instead of include guards
- use LAYOUT instead of KEYMAP
- allow customisation with matrix_init_user() and matrix_scan_user()
- set BOOTLOADER instead of BOOTLOADER_SIZE
- Add XT_ENABLE to OPT_DEFS
* Remove unnecessary lines
Diffstat (limited to 'tmk_core')
| -rw-r--r-- | tmk_core/protocol.mk | 5 | ||||
| -rw-r--r-- | tmk_core/protocol/xt.h | 71 | ||||
| -rw-r--r-- | tmk_core/protocol/xt_interrupt.c | 173 |
3 files changed, 249 insertions, 0 deletions
diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index 54913329e..78b9deb29 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk | |||
| @@ -50,5 +50,10 @@ ifdef ADB_MOUSE_ENABLE | |||
| 50 | OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE | 50 | OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE |
| 51 | endif | 51 | endif |
| 52 | 52 | ||
| 53 | ifdef XT_ENABLE | ||
| 54 | SRC += $(PROTOCOL_DIR)/xt_interrupt.c | ||
| 55 | OPT_DEFS += -DXT_ENABLE | ||
| 56 | endif | ||
| 57 | |||
| 53 | # Search Path | 58 | # Search Path |
| 54 | VPATH += $(TMK_DIR)/protocol | 59 | VPATH += $(TMK_DIR)/protocol |
diff --git a/tmk_core/protocol/xt.h b/tmk_core/protocol/xt.h new file mode 100644 index 000000000..93bc5daf8 --- /dev/null +++ b/tmk_core/protocol/xt.h | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2018 Jun WAKO <wakojun@gmail.com> | ||
| 3 | Copyright 2016 Ethan Apodaca <papodaca@gmail.com> | ||
| 4 | |||
| 5 | This software is licensed with a Modified BSD License. | ||
| 6 | All of this is supposed to be Free Software, Open Source, DFSG-free, | ||
| 7 | GPL-compatible, and OK to use in both free and proprietary applications. | ||
| 8 | Additions and corrections to this file are welcome. | ||
| 9 | |||
| 10 | |||
| 11 | Redistribution and use in source and binary forms, with or without | ||
| 12 | modification, are permitted provided that the following conditions are met: | ||
| 13 | |||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | notice, this list of conditions and the following disclaimer. | ||
| 16 | |||
| 17 | * Redistributions in binary form must reproduce the above copyright | ||
| 18 | notice, this list of conditions and the following disclaimer in | ||
| 19 | the documentation and/or other materials provided with the | ||
| 20 | distribution. | ||
| 21 | |||
| 22 | * Neither the name of the copyright holders nor the names of | ||
| 23 | contributors may be used to endorse or promote products derived | ||
| 24 | from this software without specific prior written permission. | ||
| 25 | |||
| 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 27 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 28 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 29 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
| 30 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 31 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 32 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
| 33 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
| 34 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| 35 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 36 | POSSIBILITY OF SUCH DAMAGE. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #ifndef XT_H | ||
| 40 | #define XT_H | ||
| 41 | |||
| 42 | #define XT_DATA_IN() do { \ | ||
| 43 | XT_DATA_DDR &= ~(1<<XT_DATA_BIT); \ | ||
| 44 | XT_DATA_PORT |= (1<<XT_DATA_BIT); \ | ||
| 45 | } while (0) | ||
| 46 | |||
| 47 | #define XT_DATA_READ() (XT_DATA_PIN&(1<<XT_DATA_BIT)) | ||
| 48 | |||
| 49 | #define XT_DATA_LO() do { \ | ||
| 50 | XT_DATA_PORT &= ~(1<<XT_DATA_BIT); \ | ||
| 51 | XT_DATA_DDR |= (1<<XT_DATA_BIT); \ | ||
| 52 | } while (0) | ||
| 53 | |||
| 54 | |||
| 55 | #define XT_CLOCK_IN() do { \ | ||
| 56 | XT_CLOCK_DDR &= ~(1<<XT_CLOCK_BIT); \ | ||
| 57 | XT_CLOCK_PORT |= (1<<XT_CLOCK_BIT); \ | ||
| 58 | } while (0) | ||
| 59 | |||
| 60 | #define XT_CLOCK_READ() (XT_CLOCK_PIN&(1<<XT_CLOCK_BIT)) | ||
| 61 | |||
| 62 | #define XT_CLOCK_LO() do { \ | ||
| 63 | XT_CLOCK_PORT &= ~(1<<XT_CLOCK_BIT); \ | ||
| 64 | XT_CLOCK_DDR |= (1<<XT_CLOCK_BIT); \ | ||
| 65 | } while (0) | ||
| 66 | |||
| 67 | |||
| 68 | void xt_host_init(void); | ||
| 69 | uint8_t xt_host_recv(void); | ||
| 70 | |||
| 71 | #endif | ||
diff --git a/tmk_core/protocol/xt_interrupt.c b/tmk_core/protocol/xt_interrupt.c new file mode 100644 index 000000000..3823bbd3a --- /dev/null +++ b/tmk_core/protocol/xt_interrupt.c | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2018 Jun WAKO <wakojun@gmail.com> | ||
| 3 | Copyright 2016 Ethan Apodaca <papodaca@gmail.com> | ||
| 4 | |||
| 5 | This software is licensed with a Modified BSD License. | ||
| 6 | All of this is supposed to be Free Software, Open Source, DFSG-free, | ||
| 7 | GPL-compatible, and OK to use in both free and proprietary applications. | ||
| 8 | Additions and corrections to this file are welcome. | ||
| 9 | |||
| 10 | |||
| 11 | Redistribution and use in source and binary forms, with or without | ||
| 12 | modification, are permitted provided that the following conditions are met: | ||
| 13 | |||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | notice, this list of conditions and the following disclaimer. | ||
| 16 | |||
| 17 | * Redistributions in binary form must reproduce the above copyright | ||
| 18 | notice, this list of conditions and the following disclaimer in | ||
| 19 | the documentation and/or other materials provided with the | ||
| 20 | distribution. | ||
| 21 | |||
| 22 | * Neither the name of the copyright holders nor the names of | ||
| 23 | contributors may be used to endorse or promote products derived | ||
| 24 | from this software without specific prior written permission. | ||
| 25 | |||
| 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 27 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 28 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 29 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
| 30 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 31 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 32 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
| 33 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
| 34 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| 35 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 36 | POSSIBILITY OF SUCH DAMAGE. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #include <stdbool.h> | ||
| 40 | #include <avr/interrupt.h> | ||
| 41 | #include <util/delay.h> | ||
| 42 | #include "xt.h" | ||
| 43 | #include "wait.h" | ||
| 44 | #include "print.h" | ||
| 45 | |||
| 46 | static inline uint8_t pbuf_dequeue(void); | ||
| 47 | static inline void pbuf_enqueue(uint8_t data); | ||
| 48 | static inline bool pbuf_has_data(void); | ||
| 49 | static inline void pbuf_clear(void); | ||
| 50 | |||
| 51 | void xt_host_init(void) | ||
| 52 | { | ||
| 53 | XT_INT_INIT(); | ||
| 54 | XT_INT_OFF(); | ||
| 55 | |||
| 56 | /* hard reset */ | ||
| 57 | #ifdef XT_RESET | ||
| 58 | XT_RESET(); | ||
| 59 | #endif | ||
| 60 | |||
| 61 | /* soft reset: pull clock line down for 20ms */ | ||
| 62 | XT_DATA_LO(); | ||
| 63 | XT_CLOCK_LO(); | ||
| 64 | _delay_ms(20); | ||
| 65 | |||
| 66 | /* input mode with pullup */ | ||
| 67 | XT_CLOCK_IN(); | ||
| 68 | XT_DATA_IN(); | ||
| 69 | |||
| 70 | XT_INT_ON(); | ||
| 71 | } | ||
| 72 | |||
| 73 | /* get data received by interrupt */ | ||
| 74 | uint8_t xt_host_recv(void) | ||
| 75 | { | ||
| 76 | if (pbuf_has_data()) { | ||
| 77 | return pbuf_dequeue(); | ||
| 78 | } else { | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | ISR(XT_INT_VECT) | ||
| 84 | { | ||
| 85 | /* | ||
| 86 | * XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data, | ||
| 87 | * which should be read on falling edge of clock. | ||
| 88 | * | ||
| 89 | * start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7 | ||
| 90 | * | ||
| 91 | * Original IBM XT keyboard sends start(0) bit while some of clones don't. | ||
| 92 | * Start(0) bit is read as low on data line while start(1) as high. | ||
| 93 | * | ||
| 94 | * https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol | ||
| 95 | */ | ||
| 96 | static enum { | ||
| 97 | START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7 | ||
| 98 | } state = START; | ||
| 99 | static uint8_t data = 0; | ||
| 100 | |||
| 101 | uint8_t dbit = XT_DATA_READ(); | ||
| 102 | |||
| 103 | // This is needed if using PCINT which can be called on both falling and rising edge | ||
| 104 | //if (XT_CLOCK_READ()) return; | ||
| 105 | |||
| 106 | switch (state) { | ||
| 107 | case START: | ||
| 108 | // ignore start(0) bit | ||
| 109 | if (!dbit) return; | ||
| 110 | break; | ||
| 111 | case BIT0 ... BIT7: | ||
| 112 | data >>= 1; | ||
| 113 | if (dbit) | ||
| 114 | data |= 0x80; | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | if (state++ == BIT7) { | ||
| 118 | pbuf_enqueue(data); | ||
| 119 | state = START; | ||
| 120 | data = 0; | ||
| 121 | } | ||
| 122 | return; | ||
| 123 | } | ||
| 124 | |||
| 125 | /*-------------------------------------------------------------------- | ||
| 126 | * Ring buffer to store scan codes from keyboard | ||
| 127 | *------------------------------------------------------------------*/ | ||
| 128 | #define PBUF_SIZE 32 | ||
| 129 | static uint8_t pbuf[PBUF_SIZE]; | ||
| 130 | static uint8_t pbuf_head = 0; | ||
| 131 | static uint8_t pbuf_tail = 0; | ||
| 132 | static inline void pbuf_enqueue(uint8_t data) | ||
| 133 | { | ||
| 134 | uint8_t sreg = SREG; | ||
| 135 | cli(); | ||
| 136 | uint8_t next = (pbuf_head + 1) % PBUF_SIZE; | ||
| 137 | if (next != pbuf_tail) { | ||
| 138 | pbuf[pbuf_head] = data; | ||
| 139 | pbuf_head = next; | ||
| 140 | } else { | ||
| 141 | print("pbuf: full\n"); | ||
| 142 | } | ||
| 143 | SREG = sreg; | ||
| 144 | } | ||
| 145 | static inline uint8_t pbuf_dequeue(void) | ||
| 146 | { | ||
| 147 | uint8_t val = 0; | ||
| 148 | |||
| 149 | uint8_t sreg = SREG; | ||
| 150 | cli(); | ||
| 151 | if (pbuf_head != pbuf_tail) { | ||
| 152 | val = pbuf[pbuf_tail]; | ||
| 153 | pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; | ||
| 154 | } | ||
| 155 | SREG = sreg; | ||
| 156 | |||
| 157 | return val; | ||
| 158 | } | ||
| 159 | static inline bool pbuf_has_data(void) | ||
| 160 | { | ||
| 161 | uint8_t sreg = SREG; | ||
| 162 | cli(); | ||
| 163 | bool has_data = (pbuf_head != pbuf_tail); | ||
| 164 | SREG = sreg; | ||
| 165 | return has_data; | ||
| 166 | } | ||
| 167 | static inline void pbuf_clear(void) | ||
| 168 | { | ||
| 169 | uint8_t sreg = SREG; | ||
| 170 | cli(); | ||
| 171 | pbuf_head = pbuf_tail = 0; | ||
| 172 | SREG = sreg; | ||
| 173 | } | ||
