aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/next_kbd.c
diff options
context:
space:
mode:
authortmk <hasu@tmk-kbd.com>2015-04-10 01:32:04 +0900
committertmk <hasu@tmk-kbd.com>2015-04-10 01:32:04 +0900
commit1a02ebcc612e9a9c0d87e02295c7258de3a70ccc (patch)
treee517f3c70bb2d542797e57d13e9023c84af230fb /tmk_core/protocol/next_kbd.c
parent6746e37088ce8ba03529c1226bd216705edb2b1f (diff)
parenta074364c3731d66b56d988c8a6c960a83ea0e0a1 (diff)
downloadqmk_firmware-1a02ebcc612e9a9c0d87e02295c7258de3a70ccc.tar.gz
qmk_firmware-1a02ebcc612e9a9c0d87e02295c7258de3a70ccc.zip
Merge commit 'a074364c3731d66b56d988c8a6c960a83ea0e0a1' as 'tmk_core'
Diffstat (limited to 'tmk_core/protocol/next_kbd.c')
-rw-r--r--tmk_core/protocol/next_kbd.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/tmk_core/protocol/next_kbd.c b/tmk_core/protocol/next_kbd.c
new file mode 100644
index 000000000..a5a07a7a8
--- /dev/null
+++ b/tmk_core/protocol/next_kbd.c
@@ -0,0 +1,204 @@
1/*
2
3NeXT non-ADB Keyboard Protocol
4
5Copyright 2013, Benjamin Gould (bgould@github.com)
6
7Based on:
8TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
9Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
10
11Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
12Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
13Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
14
15This software is licensed with a Modified BSD License.
16All of this is supposed to be Free Software, Open Source, DFSG-free,
17GPL-compatible, and OK to use in both free and proprietary applications.
18Additions and corrections to this file are welcome.
19
20Redistribution and use in source and binary forms, with or without
21modification, are permitted provided that the following conditions are met:
22
23* Redistributions of source code must retain the above copyright
24 notice, this list of conditions and the following disclaimer.
25
26* Redistributions in binary form must reproduce the above copyright
27 notice, this list of conditions and the following disclaimer in
28 the documentation and/or other materials provided with the
29 distribution.
30
31* Neither the name of the copyright holders nor the names of
32 contributors may be used to endorse or promote products derived
33 from this software without specific prior written permission.
34
35THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
39LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45POSSIBILITY OF SUCH DAMAGE.
46
47*/
48
49#include <stdint.h>
50#include <stdbool.h>
51#include <util/atomic.h>
52#include <util/delay.h>
53#include "next_kbd.h"
54#include "debug.h"
55
56static inline void out_lo(void);
57static inline void out_hi(void);
58static inline void query(void);
59static inline void reset(void);
60static inline uint32_t response(void);
61
62#define out_hi_delay(intervals) do { out_hi(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
63#define out_lo_delay(intervals) do { out_lo(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
64#define query_delay(intervals) do { query(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
65#define reset_delay(intervals) do { reset(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
66
67void next_kbd_init(void)
68{
69 out_hi();
70 NEXT_KBD_IN_DDR &= ~(1<<NEXT_KBD_IN_BIT); // KBD_IN to input
71 NEXT_KBD_IN_PORT |= (1<<NEXT_KBD_IN_BIT); // KBD_IN pull up
72
73 query_delay(5);
74 reset_delay(8);
75
76 query_delay(5);
77 reset_delay(8);
78}
79
80void next_kbd_set_leds(bool left, bool right)
81{
82 out_lo_delay(9);
83
84 out_hi_delay(3);
85 out_lo_delay(1);
86
87 if (left) {
88 out_hi_delay(1);
89 } else {
90 out_lo_delay(1);
91 }
92
93 if (right) {
94 out_hi_delay(1);
95 } else {
96 out_lo_delay(1);
97 }
98
99 out_lo_delay(7);
100 out_hi();
101}
102
103#define NEXT_KBD_READ (NEXT_KBD_IN_PIN&(1<<NEXT_KBD_IN_BIT))
104uint32_t next_kbd_recv(void)
105{
106
107 // First check to make sure that the keyboard is actually connected;
108 // if not, just return
109 // TODO: reflect the status of the keyboard in a return code
110 if (!NEXT_KBD_READ) {
111 sei();
112 return 0;
113 }
114
115 query();
116 uint32_t resp = response();
117
118 return resp;
119}
120
121static inline uint32_t response(void)
122{
123 cli();
124
125 // try a 5ms read; this should be called after the query method has
126 // been run so if a key is pressed we should get a response within
127 // 5ms; if not then send a reset and exit
128 uint8_t i = 0;
129 uint32_t data = 0;
130 uint16_t reset_timeout = 50000;
131 while (NEXT_KBD_READ && reset_timeout) {
132 asm(""); _delay_us(1); reset_timeout--;
133 }
134 if (!reset_timeout) {
135 reset();
136 sei();
137 return 0;
138 }
139 _delay_us(NEXT_KBD_TIMING / 2);
140 for (; i < 22; i++)
141 {
142 if (NEXT_KBD_READ)
143 {
144 data |= ((uint32_t) 1 << i);
145 /* Note:
146 * My testing with the ATmega32u4 showed that there might
147 * something wrong with the timing here; by the end of the
148 * second data byte some of the modifiers can get bumped out
149 * to the next bit over if we just cycle through the data
150 * based on the expected interval. There is a bit (i = 10)
151 * in the middle of the data that is always on followed by
152 * one that is always off - so we'll use that to reset our
153 * timing in case we've gotten ahead of the keyboard;
154 */
155 if (i == 10)
156 {
157 i++;
158 while (NEXT_KBD_READ) ;
159 _delay_us(NEXT_KBD_TIMING / 2);
160 }
161 } else {
162 /* redundant - but I don't want to remove if it might screw
163 * up the timing
164 */
165 data |= ((uint32_t) 0 << i);
166 }
167 _delay_us(NEXT_KBD_TIMING);
168 }
169
170 sei();
171
172 return data;
173}
174
175static inline void out_lo(void)
176{
177 NEXT_KBD_OUT_PORT &= ~(1<<NEXT_KBD_OUT_BIT);
178 NEXT_KBD_OUT_DDR |= (1<<NEXT_KBD_OUT_BIT);
179}
180
181static inline void out_hi(void)
182{
183 /* input with pull up */
184 NEXT_KBD_OUT_DDR &= ~(1<<NEXT_KBD_OUT_BIT);
185 NEXT_KBD_OUT_PORT |= (1<<NEXT_KBD_OUT_BIT);
186}
187
188static inline void query(void)
189{
190 out_lo_delay(5);
191 out_hi_delay(1);
192 out_lo_delay(3);
193 out_hi();
194}
195
196static inline void reset(void)
197{
198 out_lo_delay(1);
199 out_hi_delay(4);
200 out_lo_delay(1);
201 out_hi_delay(6);
202 out_lo_delay(10);
203 out_hi();
204}