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
					
				
					 2 changed files with 229 additions and 85 deletions
				
			
		|  | @ -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> | ||||
| 
 | ||||
| This software is licensed with a Modified BSD License. | ||||
|  | @ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. | |||
| #include <avr/io.h> | ||||
| #include <avr/interrupt.h> | ||||
| #include "adb.h" | ||||
| #include "print.h" | ||||
| 
 | ||||
| // GCC doesn't inline functions normally
 | ||||
| #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 uint16_t wait_data_lo(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) { | ||||
|     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.msg1070139#msg1070139>
 | ||||
|  */ | ||||
| 
 | ||||
| // 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); } | ||||
| uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); } | ||||
| 
 | ||||
| #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 | ||||
| 
 | ||||
| static inline uint16_t adb_host_dev_recv(uint8_t device) { | ||||
|     uint16_t data = 0; | ||||
| // This sends Talk command to read data from register and returns length of the data.
 | ||||
| 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(); | ||||
|     attention(); | ||||
|     send_byte(device | 0x0C);  // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00)
 | ||||
|     place_bit0();              // Stopbit(0)
 | ||||
|     send_byte((addr << 4) | ADB_CMD_TALK | reg); | ||||
|     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
 | ||||
|         xprintf("R"); | ||||
|         sei(); | ||||
|         return -30;  // something wrong
 | ||||
|         return 0; | ||||
|     } | ||||
|     if (!wait_data_lo(500)) {  // Tlt/Stop to Start(140-260us)
 | ||||
|         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 { | ||||
|         //
 | ||||
|         // |<- bit_cell_max(130) ->|
 | ||||
|         // |        |<-   lo     ->|
 | ||||
|         // |        |       |<-hi->|
 | ||||
|         //           _______
 | ||||
|         // |        |       |
 | ||||
|         // | 130-lo | lo-hi |
 | ||||
|         // |________|       |
 | ||||
|         //
 | ||||
|         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); | ||||
|         if (!hi) goto error; | ||||
|         if (!hi) goto error;  // stop bit extedned by Srq?
 | ||||
| 
 | ||||
|         hi = lo - hi; | ||||
|         lo = 130 - lo; | ||||
|         if (n / 8 >= len) continue;  // can't store in buf
 | ||||
| 
 | ||||
|         data <<= 1; | ||||
|         if (lo < hi) { | ||||
|             data |= 1; | ||||
|         } else if (n == 17) { | ||||
|             sei(); | ||||
|             return -20; | ||||
|         buf[n / 8] <<= 1; | ||||
|         if ((130 - lo) < (lo - hi)) { | ||||
|             buf[n / 8] |= 1; | ||||
|         } | ||||
|     } 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; | ||||
|     } while (++n); | ||||
| 
 | ||||
| error: | ||||
|     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(); | ||||
|     attention(); | ||||
|     send_byte(cmd); | ||||
|     place_bit0();    // Stopbit(0)
 | ||||
|     send_byte((addr << 4) | ADB_CMD_LISTEN | reg); | ||||
|     place_bit0();  // Stopbit(0)
 | ||||
|     // TODO: Service Request
 | ||||
|     _delay_us(200);  // Tlt/Stop to Start
 | ||||
|     place_bit1();    // Startbit(1)
 | ||||
|     send_byte(data_h); | ||||
|     send_byte(data_l); | ||||
|     for (int8_t i = 0; i < len; i++) { | ||||
|         send_byte(buf[i]); | ||||
|         // xprintf("%02X ", buf[i]);
 | ||||
|     } | ||||
|     place_bit0();  // Stopbit(0);
 | ||||
|     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
 | ||||
| void adb_host_kbd_led(uint8_t led) { | ||||
|     // Addr:Keyboard(0010), Cmd:Listen(10), Register2(10)
 | ||||
|     // send upper byte (not used)
 | ||||
|     // send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0:
 | ||||
|     adb_host_listen(0x2A, 0, led & 0x07); | ||||
|     // Listen Register2
 | ||||
|     //  upper byte: not used
 | ||||
|     //  lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock
 | ||||
|     adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07); | ||||
| } | ||||
| 
 | ||||
| #ifdef ADB_PSW_BIT | ||||
|  | @ -327,7 +372,7 @@ 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) | ||||
|     - - - - 0 0 1 0     Reserved | ||||
|     - - - - 0 0 1 1     Reserved | ||||
|  | @ -435,5 +480,56 @@ Keyboard LEDs & state of keys(Register2) | |||
|      | +-----------------------------   Delete | ||||
|      +-------------------------------   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 | ||||
| */ | ||||
|  |  | |||
|  | @ -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. | ||||
| 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_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
 | ||||
| void     adb_host_init(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_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); | ||||
| void     adb_mouse_task(void); | ||||
| void     adb_mouse_init(void); | ||||
| 
 | ||||
| // ADB Mouse
 | ||||
| void adb_mouse_task(void); | ||||
| void adb_mouse_init(void); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 siggie0815
						siggie0815