aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--converter/adb_usb/led.c5
-rw-r--r--converter/adb_usb/matrix.c7
-rw-r--r--protocol/adb.c208
3 files changed, 108 insertions, 112 deletions
diff --git a/converter/adb_usb/led.c b/converter/adb_usb/led.c
index 0e162f379..1e7911f94 100644
--- a/converter/adb_usb/led.c
+++ b/converter/adb_usb/led.c
@@ -15,12 +15,15 @@ You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>. 15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17 17
18#include "stdint.h" 18#include <stdint.h>
19#include <util/delay.h>
19#include "adb.h" 20#include "adb.h"
20#include "led.h" 21#include "led.h"
21 22
22 23
23void led_set(uint8_t usb_led) 24void led_set(uint8_t usb_led)
24{ 25{
26 // need a wait to send command without miss
27 _delay_ms(100);
25 adb_host_kbd_led(~usb_led); 28 adb_host_kbd_led(~usb_led);
26} 29}
diff --git a/converter/adb_usb/matrix.c b/converter/adb_usb/matrix.c
index 7e5856971..54be2b0f5 100644
--- a/converter/adb_usb/matrix.c
+++ b/converter/adb_usb/matrix.c
@@ -67,6 +67,13 @@ uint8_t matrix_cols(void)
67void matrix_init(void) 67void matrix_init(void)
68{ 68{
69 adb_host_init(); 69 adb_host_init();
70 // wait for keyboard to boot up and receive command
71 _delay_ms(1000);
72 // Enable keyboard left/right modifier distinction
73 // Addr:Keyboard(0010), Cmd:Listen(10), Register3(11)
74 // upper byte: reserved bits 0000, device address 0010
75 // lower byte: device handler 00000011
76 adb_host_listen(0x2B,0x02,0x03);
70 77
71 // initialize matrix state: all keys off 78 // initialize matrix state: all keys off
72 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; 79 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
diff --git a/protocol/adb.c b/protocol/adb.c
index f706255ad..750f4b965 100644
--- a/protocol/adb.c
+++ b/protocol/adb.c
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2011 Jun WAKO <wakojun@gmail.com> 2Copyright 2011 Jun WAKO <wakojun@gmail.com>
3Copyright 2013 Shay Green <gblargg@gmail.com>
3 4
4This software is licensed with a Modified BSD License. 5This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free, 6All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -43,9 +44,11 @@ POSSIBILITY OF SUCH DAMAGE.
43#include "debug.h" 44#include "debug.h"
44 45
45 46
46static inline void data_lo(void); 47// GCC doesn't inline functions normally
47static inline void data_hi(void); 48#define data_lo() (ADB_DDR |= (1<<ADB_DATA_BIT))
48static inline bool data_in(void); 49#define data_hi() (ADB_DDR &= ~(1<<ADB_DATA_BIT))
50#define data_in() (ADB_PIN & (1<<ADB_DATA_BIT))
51
49#ifdef ADB_PSW_BIT 52#ifdef ADB_PSW_BIT
50static inline void psw_lo(void); 53static inline void psw_lo(void);
51static inline void psw_hi(void); 54static inline void psw_hi(void);
@@ -56,24 +59,17 @@ static inline void attention(void);
56static inline void place_bit0(void); 59static inline void place_bit0(void);
57static inline void place_bit1(void); 60static inline void place_bit1(void);
58static inline void send_byte(uint8_t data); 61static inline void send_byte(uint8_t data);
59static inline bool read_bit(void); 62static inline uint16_t wait_data_lo(uint16_t us);
60static inline uint8_t read_byte(void); 63static inline uint16_t wait_data_hi(uint16_t us);
61static inline uint8_t wait_data_lo(uint16_t us);
62static inline uint8_t wait_data_hi(uint8_t us);
63 64
64 65
65void adb_host_init(void) 66void adb_host_init(void)
66{ 67{
68 ADB_PORT &= ~(1<<ADB_DATA_BIT);
67 data_hi(); 69 data_hi();
68#ifdef ADB_PSW_BIT 70#ifdef ADB_PSW_BIT
69 psw_hi(); 71 psw_hi();
70#endif 72#endif
71
72 // Enable keyboard left/right modifier distinction
73 // Addr:Keyboard(0010), Cmd:Listen(10), Register3(11)
74 // upper byte: reserved bits 0000, device address 0010
75 // lower byte: device handler 00000011
76 adb_host_listen(0x2B,0x02,0x03);
77} 73}
78 74
79#ifdef ADB_PSW_BIT 75#ifdef ADB_PSW_BIT
@@ -91,6 +87,41 @@ bool adb_host_psw(void)
91 * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> 87 * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
92 * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> 88 * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
93 */ 89 */
90
91// ADB Bit Cells
92//
93// bit cell time: 70-130us
94// low part of bit0: 60-70% of bit cell
95// low part of bit1: 30-40% of bit cell
96//
97// bit cell time 70us 130us
98// --------------------------------------------
99// low part of bit0 42-49 78-91
100// high part of bit0 21-28 39-52
101// low part of bit1 21-28 39-52
102// high part of bit1 42-49 78-91
103//
104//
105// bit0:
106// 70us bit cell:
107// ____________~~~~~~
108// 42-49 21-28
109//
110// 130us bit cell:
111// ____________~~~~~~
112// 78-91 39-52
113//
114// bit1:
115// 70us bit cell:
116// ______~~~~~~~~~~~~
117// 21-28 42-49
118//
119// 130us bit cell:
120// ______~~~~~~~~~~~~
121// 39-52 78-91
122//
123// [from Apple IIgs Hardware Reference Second Edition]
124
94uint16_t adb_host_kbd_recv(void) 125uint16_t adb_host_kbd_recv(void)
95{ 126{
96 uint16_t data = 0; 127 uint16_t data = 0;
@@ -100,24 +131,50 @@ uint16_t adb_host_kbd_recv(void)
100 if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) 131 if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
101 return 0; // No data to send 132 return 0; // No data to send
102 } 133 }
103 if (!read_bit()) { // Startbit(1) 134
104 // Service Request
105 dprintf("Startbit ERROR\n");
106 return -2;
107 }
108
109 // ad hoc fix: without block inerrupt read wrong bit occasionally and get keys stuck 135 // ad hoc fix: without block inerrupt read wrong bit occasionally and get keys stuck
110 cli(); 136 // TODO: is this needed anymore with improved timing?
111 data = read_byte(); 137 //cli();
112 data = (data<<8) | read_byte(); 138 uint8_t n = 17; // start bit + 16 data bits
113 uint8_t stop = read_bit(); // Stopbit(0) 139 do {
114 sei(); 140 uint8_t lo = (uint8_t) wait_data_hi(130);
141 if (!lo)
142 goto error;
143
144 uint8_t hi = (uint8_t) wait_data_lo(lo);
145 if (!hi)
146 goto error;
147
148 hi = lo - hi;
149 lo = 130 - lo;
150
151 data <<= 1;
152 if (lo < hi) {
153 data |= 1;
154 }
155 else if (n == 17) {
156 // Service Request
157 dprintf("Startbit ERROR\n");
158 sei();
159 return -2;
160 }
161 }
162 while ( --n );
115 163
116 if (stop) { 164 // Stop bit can't be checked normally since it could have service request lenghtening
165 // and its high state never goes low.
166 if (!wait_data_hi(351) || wait_data_lo(91)) {
117 dprintf("Stopbit ERROR\n"); 167 dprintf("Stopbit ERROR\n");
168 sei();
118 return -3; 169 return -3;
119 } 170 }
171 sei();
120 return data; 172 return data;
173
174error:
175 dprintf("Bit ERROR\n");
176 sei();
177 return -4;
121} 178}
122 179
123void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) 180void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l)
@@ -142,23 +199,6 @@ void adb_host_kbd_led(uint8_t led)
142} 199}
143 200
144 201
145static inline void data_lo()
146{
147 ADB_DDR |= (1<<ADB_DATA_BIT);
148 ADB_PORT &= ~(1<<ADB_DATA_BIT);
149}
150static inline void data_hi()
151{
152 ADB_PORT |= (1<<ADB_DATA_BIT);
153 ADB_DDR &= ~(1<<ADB_DATA_BIT);
154}
155static inline bool data_in()
156{
157 ADB_PORT |= (1<<ADB_DATA_BIT);
158 ADB_DDR &= ~(1<<ADB_DATA_BIT);
159 return ADB_PIN&(1<<ADB_DATA_BIT);
160}
161
162#ifdef ADB_PSW_BIT 202#ifdef ADB_PSW_BIT
163static inline void psw_lo() 203static inline void psw_lo()
164{ 204{
@@ -181,7 +221,7 @@ static inline bool psw_in()
181static inline void attention(void) 221static inline void attention(void)
182{ 222{
183 data_lo(); 223 data_lo();
184 _delay_us(700); 224 _delay_us(800-35); // bit1 holds lo for 35 more
185 place_bit1(); 225 place_bit1();
186} 226}
187 227
@@ -211,81 +251,27 @@ static inline void send_byte(uint8_t data)
211 } 251 }
212} 252}
213 253
214static inline bool read_bit(void) 254// These are carefully coded to take 6 cycles of overhead.
215{ 255// inline asm approach became too convoluted
216 // ADB Bit Cells 256static inline uint16_t wait_data_lo(uint16_t us)
217 //
218 // bit cell time: 70-130us
219 // low part of bit0: 60-70% of bit cell
220 // low part of bit1: 30-40% of bit cell
221 //
222 // bit cell time 70us 130us
223 // --------------------------------------------
224 // low part of bit0 42-49 78-91
225 // high part of bit0 21-28 39-52
226 // low part of bit1 21-28 39-52
227 // high part of bit1 42-49 78-91
228 //
229 //
230 // bit0:
231 // 70us bit cell:
232 // ____________~~~~~~
233 // 42-49 21-28
234 //
235 // 130us bit cell:
236 // ____________~~~~~~
237 // 78-91 39-52
238 //
239 // bit1:
240 // 70us bit cell:
241 // ______~~~~~~~~~~~~
242 // 21-28 42-49
243 //
244 // 130us bit cell:
245 // ______~~~~~~~~~~~~
246 // 39-52 78-91
247 //
248 // read:
249 // ________|~~~~~~~~~
250 // 55us
251 // Read data line after 55us. If data line is low/high then bit is 0/1.
252 // This method might not work at <90us bit cell time.
253 //
254 // [from Apple IIgs Hardware Reference Second Edition]
255 bool bit;
256 wait_data_lo(75); // wait the start of bit cell at least 130ms(55+0+75)
257 _delay_us(55);
258 bit = data_in();
259 wait_data_hi(36); // wait high part of bit cell at least 91ms(55+36)
260 return bit;
261}
262
263static inline uint8_t read_byte(void)
264{
265 uint8_t data = 0;
266 for (int i = 0; i < 8; i++) {
267 data <<= 1;
268 if (read_bit())
269 data = data | 1;
270 }
271 return data;
272}
273
274static inline uint8_t wait_data_lo(uint16_t us)
275{ 257{
276 while (data_in() && us) { 258 do {
277 _delay_us(1); 259 if ( !data_in() )
278 us--; 260 break;
261 _delay_us(1 - (6 * 1000000.0 / F_CPU));
279 } 262 }
263 while ( --us );
280 return us; 264 return us;
281} 265}
282 266
283static inline uint8_t wait_data_hi(uint8_t us) 267static inline uint16_t wait_data_hi(uint16_t us)
284{ 268{
285 while (!data_in() && us) { 269 do {
286 _delay_us(1); 270 if ( data_in() )
287 us--; 271 break;
272 _delay_us(1 - (6 * 1000000.0 / F_CPU));
288 } 273 }
274 while ( --us );
289 return us; 275 return us;
290} 276}
291 277