Update ADB impelemtation in TMK Core (#11168)
* Update ADB impelmentation in tmk_core to recent version. Pcked from tmk_keyboard repository revision: 48d696443857512d45f9a7329e0dd0a76345860f * Restore convenient ADB functions used in QMK port. * Do cformat.
This commit is contained in:
parent
9410b15ac9
commit
1b3504e329
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2011 Jun WAKO <wakojun@gmail.com>
|
Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
|
||||||
Copyright 2013 Shay Green <gblargg@gmail.com>
|
Copyright 2013 Shay Green <gblargg@gmail.com>
|
||||||
|
|
||||||
This software is licensed with a Modified BSD License.
|
This software is licensed with a Modified BSD License.
|
||||||
|
@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include "adb.h"
|
#include "adb.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
// GCC doesn't inline functions normally
|
// GCC doesn't inline functions normally
|
||||||
#define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT))
|
#define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT))
|
||||||
|
@ -59,7 +60,6 @@ static inline void place_bit1(void);
|
||||||
static inline void send_byte(uint8_t data);
|
static inline void send_byte(uint8_t data);
|
||||||
static inline uint16_t wait_data_lo(uint16_t us);
|
static inline uint16_t wait_data_lo(uint16_t us);
|
||||||
static inline uint16_t wait_data_hi(uint16_t us);
|
static inline uint16_t wait_data_hi(uint16_t us);
|
||||||
static inline uint16_t adb_host_dev_recv(uint8_t device);
|
|
||||||
|
|
||||||
void adb_host_init(void) {
|
void adb_host_init(void) {
|
||||||
ADB_PORT &= ~(1 << ADB_DATA_BIT);
|
ADB_PORT &= ~(1 << ADB_DATA_BIT);
|
||||||
|
@ -81,119 +81,164 @@ bool adb_host_psw(void) { return psw_in(); }
|
||||||
* <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
|
* <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
|
||||||
* <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
|
* <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
|
||||||
*/
|
*/
|
||||||
|
uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); }
|
||||||
// ADB Bit Cells
|
|
||||||
//
|
|
||||||
// bit cell time: 70-130us
|
|
||||||
// low part of bit0: 60-70% of bit cell
|
|
||||||
// low part of bit1: 30-40% of bit cell
|
|
||||||
//
|
|
||||||
// bit cell time 70us 130us
|
|
||||||
// --------------------------------------------
|
|
||||||
// low part of bit0 42-49 78-91
|
|
||||||
// high part of bit0 21-28 39-52
|
|
||||||
// low part of bit1 21-28 39-52
|
|
||||||
// high part of bit1 42-49 78-91
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// bit0:
|
|
||||||
// 70us bit cell:
|
|
||||||
// ____________~~~~~~
|
|
||||||
// 42-49 21-28
|
|
||||||
//
|
|
||||||
// 130us bit cell:
|
|
||||||
// ____________~~~~~~
|
|
||||||
// 78-91 39-52
|
|
||||||
//
|
|
||||||
// bit1:
|
|
||||||
// 70us bit cell:
|
|
||||||
// ______~~~~~~~~~~~~
|
|
||||||
// 21-28 42-49
|
|
||||||
//
|
|
||||||
// 130us bit cell:
|
|
||||||
// ______~~~~~~~~~~~~
|
|
||||||
// 39-52 78-91
|
|
||||||
//
|
|
||||||
// [from Apple IIgs Hardware Reference Second Edition]
|
|
||||||
|
|
||||||
enum { ADDR_KEYB = 0x20, ADDR_MOUSE = 0x30 };
|
|
||||||
|
|
||||||
uint16_t adb_host_kbd_recv(void) { return adb_host_dev_recv(ADDR_KEYB); }
|
|
||||||
|
|
||||||
#ifdef ADB_MOUSE_ENABLE
|
#ifdef ADB_MOUSE_ENABLE
|
||||||
void adb_mouse_init(void) { return; }
|
__attribute__((weak)) void adb_mouse_init(void) { return; }
|
||||||
|
|
||||||
uint16_t adb_host_mouse_recv(void) { return adb_host_dev_recv(ADDR_MOUSE); }
|
__attribute__((weak)) void adb_mouse_task(void) { return; }
|
||||||
|
|
||||||
|
uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline uint16_t adb_host_dev_recv(uint8_t device) {
|
// This sends Talk command to read data from register and returns length of the data.
|
||||||
uint16_t data = 0;
|
uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
|
||||||
|
for (int8_t i = 0; i < len; i++) buf[i] = 0;
|
||||||
|
|
||||||
cli();
|
cli();
|
||||||
attention();
|
attention();
|
||||||
send_byte(device | 0x0C); // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00)
|
send_byte((addr << 4) | ADB_CMD_TALK | reg);
|
||||||
place_bit0(); // Stopbit(0)
|
place_bit0(); // Stopbit(0)
|
||||||
|
// TODO: Service Request(Srq):
|
||||||
|
// Device holds low part of comannd stopbit for 140-260us
|
||||||
|
//
|
||||||
|
// Command:
|
||||||
|
// ......._ ______________________ ___ ............_ -------
|
||||||
|
// | | | | | | |
|
||||||
|
// Command | | | | | Data bytes | |
|
||||||
|
// ........|___| | 140-260 |__| |_............|___|
|
||||||
|
// |stop0 | Tlt Stop-to-Start |start1| |stop0 |
|
||||||
|
//
|
||||||
|
// Command without data:
|
||||||
|
// ......._ __________________________
|
||||||
|
// | |
|
||||||
|
// Command | |
|
||||||
|
// ........|___| | 140-260 |
|
||||||
|
// |stop0 | Tlt Stop-to-Start |
|
||||||
|
//
|
||||||
|
// Service Request:
|
||||||
|
// ......._ ______ ___ ............_ -------
|
||||||
|
// | 140-260 | | | | | |
|
||||||
|
// Command | Service Request | | | | Data bytes | |
|
||||||
|
// ........|___________________| |__| |_............|___|
|
||||||
|
// |stop0 | |start1| |stop0 |
|
||||||
|
// ......._ __________
|
||||||
|
// | 140-260 |
|
||||||
|
// Command | Service Request |
|
||||||
|
// ........|___________________|
|
||||||
|
// |stop0 |
|
||||||
|
// This can be happened?
|
||||||
|
// ......._ ______________________ ___ ............_ -----
|
||||||
|
// | | | | | | 140-260 |
|
||||||
|
// Command | | | | | Data bytes | Service Request |
|
||||||
|
// ........|___| | 140-260 |__| |_............|_________________|
|
||||||
|
// |stop0 | Tlt Stop-to-Start |start1| |stop0 |
|
||||||
|
//
|
||||||
|
// "Service requests are issued by the devices during a very specific time at the
|
||||||
|
// end of the reception of the command packet.
|
||||||
|
// If a device in need of service issues a service request, it must do so within
|
||||||
|
// the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs."
|
||||||
|
//
|
||||||
|
// "A device sends a Service Request signal by holding the bus low during the low
|
||||||
|
// portion of the stop bit of any command or data transaction. The device must lengthen
|
||||||
|
// the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15."
|
||||||
|
// http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf
|
||||||
if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
|
if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
|
||||||
|
xprintf("R");
|
||||||
sei();
|
sei();
|
||||||
return -30; // something wrong
|
return 0;
|
||||||
}
|
}
|
||||||
if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
|
if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
|
||||||
sei();
|
sei();
|
||||||
return 0; // No data to send
|
return 0; // No data from device(not error);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t n = 17; // start bit + 16 data bits
|
// start bit(1)
|
||||||
|
if (!wait_data_hi(40)) {
|
||||||
|
xprintf("S");
|
||||||
|
sei();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!wait_data_lo(100)) {
|
||||||
|
xprintf("s");
|
||||||
|
sei();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t n = 0; // bit count
|
||||||
do {
|
do {
|
||||||
|
//
|
||||||
|
// |<- bit_cell_max(130) ->|
|
||||||
|
// | |<- lo ->|
|
||||||
|
// | | |<-hi->|
|
||||||
|
// _______
|
||||||
|
// | | |
|
||||||
|
// | 130-lo | lo-hi |
|
||||||
|
// |________| |
|
||||||
|
//
|
||||||
uint8_t lo = (uint8_t)wait_data_hi(130);
|
uint8_t lo = (uint8_t)wait_data_hi(130);
|
||||||
if (!lo) goto error;
|
if (!lo) goto error; // no more bit or after stop bit
|
||||||
|
|
||||||
uint8_t hi = (uint8_t)wait_data_lo(lo);
|
uint8_t hi = (uint8_t)wait_data_lo(lo);
|
||||||
if (!hi) goto error;
|
if (!hi) goto error; // stop bit extedned by Srq?
|
||||||
|
|
||||||
hi = lo - hi;
|
if (n / 8 >= len) continue; // can't store in buf
|
||||||
lo = 130 - lo;
|
|
||||||
|
|
||||||
data <<= 1;
|
buf[n / 8] <<= 1;
|
||||||
if (lo < hi) {
|
if ((130 - lo) < (lo - hi)) {
|
||||||
data |= 1;
|
buf[n / 8] |= 1;
|
||||||
} else if (n == 17) {
|
|
||||||
sei();
|
|
||||||
return -20;
|
|
||||||
}
|
}
|
||||||
} while (--n);
|
} while (++n);
|
||||||
|
|
||||||
// Stop bit can't be checked normally since it could have service request lenghtening
|
|
||||||
// and its high state never goes low.
|
|
||||||
if (!wait_data_hi(351) || wait_data_lo(91)) {
|
|
||||||
sei();
|
|
||||||
return -21;
|
|
||||||
}
|
|
||||||
sei();
|
|
||||||
return data;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
sei();
|
sei();
|
||||||
return -n;
|
return n / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) {
|
uint16_t adb_host_talk(uint8_t addr, uint8_t reg) {
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t buf[8];
|
||||||
|
len = adb_host_talk_buf(addr, reg, buf, 8);
|
||||||
|
if (len != 2) return 0;
|
||||||
|
return (buf[0] << 8 | buf[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) {
|
||||||
cli();
|
cli();
|
||||||
attention();
|
attention();
|
||||||
send_byte(cmd);
|
send_byte((addr << 4) | ADB_CMD_LISTEN | reg);
|
||||||
place_bit0(); // Stopbit(0)
|
place_bit0(); // Stopbit(0)
|
||||||
|
// TODO: Service Request
|
||||||
_delay_us(200); // Tlt/Stop to Start
|
_delay_us(200); // Tlt/Stop to Start
|
||||||
place_bit1(); // Startbit(1)
|
place_bit1(); // Startbit(1)
|
||||||
send_byte(data_h);
|
for (int8_t i = 0; i < len; i++) {
|
||||||
send_byte(data_l);
|
send_byte(buf[i]);
|
||||||
|
// xprintf("%02X ", buf[i]);
|
||||||
|
}
|
||||||
place_bit0(); // Stopbit(0);
|
place_bit0(); // Stopbit(0);
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) {
|
||||||
|
uint8_t buf[2] = {data_h, data_l};
|
||||||
|
adb_host_listen_buf(addr, reg, buf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adb_host_flush(uint8_t addr) {
|
||||||
|
cli();
|
||||||
|
attention();
|
||||||
|
send_byte((addr << 4) | ADB_CMD_FLUSH);
|
||||||
|
place_bit0(); // Stopbit(0)
|
||||||
|
_delay_us(200); // Tlt/Stop to Start
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
|
||||||
// send state of LEDs
|
// send state of LEDs
|
||||||
void adb_host_kbd_led(uint8_t led) {
|
void adb_host_kbd_led(uint8_t led) {
|
||||||
// Addr:Keyboard(0010), Cmd:Listen(10), Register2(10)
|
// Listen Register2
|
||||||
// send upper byte (not used)
|
// upper byte: not used
|
||||||
// send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0:
|
// lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock
|
||||||
adb_host_listen(0x2A, 0, led & 0x07);
|
adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADB_PSW_BIT
|
#ifdef ADB_PSW_BIT
|
||||||
|
@ -327,7 +372,7 @@ Commands
|
||||||
|
|
||||||
bits commands
|
bits commands
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
- - - - 0 0 0 0 Send Request(reset all devices)
|
- - - - 0 0 0 0 Send Reset(reset all devices)
|
||||||
A A A A 0 0 0 1 Flush(reset a device)
|
A A A A 0 0 0 1 Flush(reset a device)
|
||||||
- - - - 0 0 1 0 Reserved
|
- - - - 0 0 1 0 Reserved
|
||||||
- - - - 0 0 1 1 Reserved
|
- - - - 0 0 1 1 Reserved
|
||||||
|
@ -435,5 +480,56 @@ Keyboard LEDs & state of keys(Register2)
|
||||||
| +----------------------------- Delete
|
| +----------------------------- Delete
|
||||||
+------------------------------- Reserved
|
+------------------------------- Reserved
|
||||||
|
|
||||||
|
Address, Handler ID and bits(Register3)
|
||||||
|
1514131211 . . 8 7 . . . . . . 0
|
||||||
|
| | | | | | | | | | | | | | | |
|
||||||
|
| | | | | | | | +-+-+-+-+-+-+-+- Handler ID
|
||||||
|
| | | | +-+-+-+----------------- Address
|
||||||
|
| | | +------------------------- 0
|
||||||
|
| | +--------------------------- Service request enable(1 = enabled)
|
||||||
|
| +----------------------------- Exceptional event(alwyas 1 if not used)
|
||||||
|
+------------------------------- 0
|
||||||
|
|
||||||
|
ADB Bit Cells
|
||||||
|
bit cell time: 70-130us
|
||||||
|
low part of bit0: 60-70% of bit cell
|
||||||
|
low part of bit1: 30-40% of bit cell
|
||||||
|
|
||||||
|
bit cell time 70us 130us
|
||||||
|
--------------------------------------------
|
||||||
|
low part of bit0 42-49 78-91
|
||||||
|
high part of bit0 21-28 39-52
|
||||||
|
low part of bit1 21-28 39-52
|
||||||
|
high part of bit1 42-49 78-91
|
||||||
|
|
||||||
|
|
||||||
|
bit0:
|
||||||
|
70us bit cell:
|
||||||
|
____________~~~~~~
|
||||||
|
42-49 21-28
|
||||||
|
|
||||||
|
130us bit cell:
|
||||||
|
____________~~~~~~
|
||||||
|
78-91 39-52
|
||||||
|
|
||||||
|
bit1:
|
||||||
|
70us bit cell:
|
||||||
|
______~~~~~~~~~~~~
|
||||||
|
21-28 42-49
|
||||||
|
|
||||||
|
130us bit cell:
|
||||||
|
______~~~~~~~~~~~~
|
||||||
|
39-52 78-91
|
||||||
|
|
||||||
|
[from Apple IIgs Hardware Reference Second Edition]
|
||||||
|
|
||||||
|
Keyboard Handle ID
|
||||||
|
Apple Standard Keyboard M0116: 0x01
|
||||||
|
Apple Extended Keyboard M0115: 0x02
|
||||||
|
Apple Extended Keyboard II M3501: 0x02
|
||||||
|
Apple Adjustable Keybaord: 0x10
|
||||||
|
|
||||||
|
http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802
|
||||||
|
|
||||||
END_OF_ADB
|
END_OF_ADB
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2011 Jun WAKO <wakojun@gmail.com>
|
Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
|
||||||
|
|
||||||
This software is licensed with a Modified BSD License.
|
This software is licensed with a Modified BSD License.
|
||||||
All of this is supposed to be Free Software, Open Source, DFSG-free,
|
All of this is supposed to be Free Software, Open Source, DFSG-free,
|
||||||
|
@ -47,12 +47,60 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define ADB_POWER 0x7F
|
#define ADB_POWER 0x7F
|
||||||
#define ADB_CAPS 0x39
|
#define ADB_CAPS 0x39
|
||||||
|
|
||||||
|
/* ADB commands */
|
||||||
|
// Default Address
|
||||||
|
#define ADB_ADDR_0 0
|
||||||
|
#define ADB_ADDR_DONGLE 1
|
||||||
|
#define ADB_ADDR_KEYBOARD 2
|
||||||
|
#define ADB_ADDR_MOUSE 3
|
||||||
|
#define ADB_ADDR_TABLET 4
|
||||||
|
#define ADB_ADDR_APPLIANCE 7
|
||||||
|
#define ADB_ADDR_8 8
|
||||||
|
#define ADB_ADDR_9 9
|
||||||
|
#define ADB_ADDR_10 10
|
||||||
|
#define ADB_ADDR_11 11
|
||||||
|
#define ADB_ADDR_12 12
|
||||||
|
#define ADB_ADDR_13 13
|
||||||
|
#define ADB_ADDR_14 14
|
||||||
|
#define ADB_ADDR_15 15
|
||||||
|
// for temporary purpose, do not use for polling
|
||||||
|
#define ADB_ADDR_TMP 15
|
||||||
|
#define ADB_ADDR_MOUSE_POLL 10
|
||||||
|
// Command Type
|
||||||
|
#define ADB_CMD_RESET 0
|
||||||
|
#define ADB_CMD_FLUSH 1
|
||||||
|
#define ADB_CMD_LISTEN 8
|
||||||
|
#define ADB_CMD_TALK 12
|
||||||
|
// Register
|
||||||
|
#define ADB_REG_0 0
|
||||||
|
#define ADB_REG_1 1
|
||||||
|
#define ADB_REG_2 2
|
||||||
|
#define ADB_REG_3 3
|
||||||
|
|
||||||
|
/* ADB keyboard handler id */
|
||||||
|
#define ADB_HANDLER_STD 0x01 /* IIGS, M0116 */
|
||||||
|
#define ADB_HANDLER_AEK 0x02 /* M0115, M3501 */
|
||||||
|
#define ADB_HANDLER_AEK_RMOD 0x03 /* M0115, M3501, alternate mode enableing right modifiers */
|
||||||
|
#define ADB_HANDLER_STD_ISO 0x04 /* M0118, ISO swapping keys */
|
||||||
|
#define ADB_HANDLER_AEK_ISO 0x05 /* M0115, M3501, ISO swapping keys */
|
||||||
|
#define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */
|
||||||
|
#define ADB_HANDLER_CLASSIC1_MOUSE 0x01
|
||||||
|
#define ADB_HANDLER_CLASSIC2_MOUSE 0x02
|
||||||
|
#define ADB_HANDLER_EXTENDED_MOUSE 0x04
|
||||||
|
#define ADB_HANDLER_TURBO_MOUSE 0x32
|
||||||
|
|
||||||
// ADB host
|
// ADB host
|
||||||
void adb_host_init(void);
|
void adb_host_init(void);
|
||||||
bool adb_host_psw(void);
|
bool adb_host_psw(void);
|
||||||
|
uint16_t adb_host_talk(uint8_t addr, uint8_t reg);
|
||||||
|
uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
|
||||||
|
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l);
|
||||||
|
void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
|
||||||
|
void adb_host_flush(uint8_t addr);
|
||||||
|
void adb_host_kbd_led(uint8_t led);
|
||||||
uint16_t adb_host_kbd_recv(void);
|
uint16_t adb_host_kbd_recv(void);
|
||||||
uint16_t adb_host_mouse_recv(void);
|
uint16_t adb_host_mouse_recv(void);
|
||||||
void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l);
|
|
||||||
void adb_host_kbd_led(uint8_t led);
|
// ADB Mouse
|
||||||
void adb_mouse_task(void);
|
void adb_mouse_task(void);
|
||||||
void adb_mouse_init(void);
|
void adb_mouse_init(void);
|
||||||
|
|
Loading…
Reference in New Issue