forked from mirrors/qmk_userspace
		
	ADB to USB keyboard converter
This commit is contained in:
		
					parent
					
						
							
								1f5cd6d7dc
							
						
					
				
			
			
				commit
				
					
						56e098d76e
					
				
			
		
					 8 changed files with 809 additions and 0 deletions
				
			
		
							
								
								
									
										134
									
								
								ADB.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								ADB.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,134 @@
 | 
				
			||||||
 | 
					ADB Protocol
 | 
				
			||||||
 | 
					============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Resources
 | 
				
			||||||
 | 
					---------
 | 
				
			||||||
 | 
					Apple IIgs Hardware Reference Second Edition [p80(Chapter6 p121)]
 | 
				
			||||||
 | 
					    ftp://ftp.apple.asimov.net/pub/apple_II/documentation/Apple%20IIgs%20Hardware%20Reference.pdf
 | 
				
			||||||
 | 
					ADB Keycode
 | 
				
			||||||
 | 
					    http://72.0.193.250/Documentation/macppc/adbkeycodes/
 | 
				
			||||||
 | 
					    http://m0115.web.fc2.com/m0115.jpg
 | 
				
			||||||
 | 
					ADB Signaling
 | 
				
			||||||
 | 
					    http://kbdbabel.sourceforge.net/doc/kbd_signaling_pcxt_ps2_adb.pdf
 | 
				
			||||||
 | 
					ADB Overview & History
 | 
				
			||||||
 | 
					    http://en.wikipedia.org/wiki/Apple_Desktop_Bus
 | 
				
			||||||
 | 
					Microchip Application Note: ADB device(with code for PIC16C)
 | 
				
			||||||
 | 
					    http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011062
 | 
				
			||||||
 | 
					AVR ATtiny2131 ADB to PS/2 converter(Japanese)
 | 
				
			||||||
 | 
					    http://hp.vector.co.jp/authors/VA000177/html/KeyBoardA5DEA5CBA5A2II.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Pinouts
 | 
				
			||||||
 | 
					-------
 | 
				
			||||||
 | 
					    Female socket from the front
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      4o  o3
 | 
				
			||||||
 | 
					     2o    o1
 | 
				
			||||||
 | 
					        ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    1: Data
 | 
				
			||||||
 | 
					    2: Power SW(low when press Power key)
 | 
				
			||||||
 | 
					    3: Vcc(5V)
 | 
				
			||||||
 | 
					    4: GND
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Commands
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					    ADB command is 1byte and consists of 4bit-address, 2bit-command
 | 
				
			||||||
 | 
					    type and 2bit-register. The commands are always sent by Host.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Command format:
 | 
				
			||||||
 | 
					    7 6 5 4 3 2 1 0
 | 
				
			||||||
 | 
					    | | | |------------ address
 | 
				
			||||||
 | 
					            | |-------- command type
 | 
				
			||||||
 | 
					                | |---- register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bits                commands
 | 
				
			||||||
 | 
					    ------------------------------------------------------
 | 
				
			||||||
 | 
					    - - - - 0 0 0 0     Send Request(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
 | 
				
			||||||
 | 
					    - - - - 0 1 - -     Reserved
 | 
				
			||||||
 | 
					    A A A A 1 0 R R     Listen(write to a device)
 | 
				
			||||||
 | 
					    A A A A 1 1 R R     Talk(read from a device)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The command to read keycodes from keyboard is 0x2C which
 | 
				
			||||||
 | 
					    consist of keyboard address 2 and Talk against register 0. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Address:
 | 
				
			||||||
 | 
					    2:  keyboard
 | 
				
			||||||
 | 
					    3:  mice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Registers:
 | 
				
			||||||
 | 
					    0: application(keyobard/mice use to store its data.)
 | 
				
			||||||
 | 
					    1: application
 | 
				
			||||||
 | 
					    2: application
 | 
				
			||||||
 | 
					    3: status and command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Communication
 | 
				
			||||||
 | 
					-------------
 | 
				
			||||||
 | 
					    This is a minimum information for keyboard communication.
 | 
				
			||||||
 | 
					    See "Resources" for detail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Signaling:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ~~~~____________~~||||||||||||__~~~~~_~~|||||||||||||||__~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        |800us     |  |7 Command 0|  |   |  |15-64  Data  0|Stopbit(0)
 | 
				
			||||||
 | 
					        +Attention |              |  |   +Startbit(1)
 | 
				
			||||||
 | 
					                   +Startbit(1)   |  +Tlt(140-260us)
 | 
				
			||||||
 | 
					                                  +stopbit(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Bit cells:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bit0: ______~~~
 | 
				
			||||||
 | 
					          65    :35us
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bit1: ___~~~~~~
 | 
				
			||||||
 | 
					          35 :65us
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bit0 low time: 60-70% of bit cell(42-91us)
 | 
				
			||||||
 | 
					    bit1 low time: 30-40% of bit cell(21-52us)
 | 
				
			||||||
 | 
					    bit cell time: 70-130us
 | 
				
			||||||
 | 
					    [from Apple IIgs Hardware Reference Second Edition]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Criterion for bit0/1:
 | 
				
			||||||
 | 
					    After 55us if line is low/high then bit is 0/1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Attention & start bit:
 | 
				
			||||||
 | 
					    Host asserts low in 560-1040us then places start bit(1).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tlt(Stop to Start):
 | 
				
			||||||
 | 
					    Bus stays high in 140-260us then device places start bit(1).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Global reset:
 | 
				
			||||||
 | 
					    Host asserts low in 2.8-5.2ms. All devices are forced to reset.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Send request from device(Srq):
 | 
				
			||||||
 | 
					    Device can request to send at commad(Global only?) stop bit.
 | 
				
			||||||
 | 
					    keep low for 300us to request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Keyboard data(register0)
 | 
				
			||||||
 | 
					    This 16bit data can contains 2 keycodes and 2 released flags.
 | 
				
			||||||
 | 
					    First keycode is palced in upper nibble. When one keyocode is sent,
 | 
				
			||||||
 | 
					    lower nibble is 0xFF.
 | 
				
			||||||
 | 
					    Release flag is 1 when key is released.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    15 14 . . . . . 8 7 6 . . . . . 0
 | 
				
			||||||
 | 
					    |  |keycode1      | |keycode2
 | 
				
			||||||
 | 
					    |released(1)      |released(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Keycodes:
 | 
				
			||||||
 | 
					    Scancode consists of 7bit keycode and 1bit release flag.
 | 
				
			||||||
 | 
					    Device can send two keycodes at once. If just one keycode is sent
 | 
				
			||||||
 | 
					    keycode1 contains it and keyocode2 is 0xFF.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Power switch:
 | 
				
			||||||
 | 
					    You can read the state from PSW line(active low) however
 | 
				
			||||||
 | 
					    the switch has a special scancode 0x7F7F, so you can
 | 
				
			||||||
 | 
					    also read from Data line. It uses 0xFFFF for release scancode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					END_OF_ADB
 | 
				
			||||||
							
								
								
									
										180
									
								
								adb.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								adb.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,180 @@
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <util/delay.h>
 | 
				
			||||||
 | 
					#include <avr/io.h>
 | 
				
			||||||
 | 
					#include "adb.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void data_lo(void);
 | 
				
			||||||
 | 
					static inline void data_hi(void);
 | 
				
			||||||
 | 
					static inline bool data_in(void);
 | 
				
			||||||
 | 
					#ifdef ADB_PSW_BIT
 | 
				
			||||||
 | 
					static inline void psw_lo(void);
 | 
				
			||||||
 | 
					static inline void psw_hi(void);
 | 
				
			||||||
 | 
					static inline bool psw_in(void);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void attention(void);
 | 
				
			||||||
 | 
					static inline void place_bit0(void);
 | 
				
			||||||
 | 
					static inline void place_bit1(void);
 | 
				
			||||||
 | 
					static inline void send_byte(uint8_t data);
 | 
				
			||||||
 | 
					static inline bool read_bit(void);
 | 
				
			||||||
 | 
					static inline uint8_t read_byte(void);
 | 
				
			||||||
 | 
					static inline uint8_t wait_data_lo(uint8_t us);
 | 
				
			||||||
 | 
					static inline uint8_t wait_data_hi(uint8_t us);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void adb_host_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    data_hi();
 | 
				
			||||||
 | 
					#ifdef ADB_PSW_BIT
 | 
				
			||||||
 | 
					    psw_hi();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ADB_PSW_BIT
 | 
				
			||||||
 | 
					bool adb_host_psw(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return psw_in();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t adb_host_kbd_recv(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t data = 0;
 | 
				
			||||||
 | 
					    attention();
 | 
				
			||||||
 | 
					    send_byte(0x2C);            // Addr:2, Cmd:talk(11), Reg:0(00)
 | 
				
			||||||
 | 
					    place_bit0();               // Stopbit
 | 
				
			||||||
 | 
					    if (!wait_data_lo(0xFF))    // Stop to Start(140-260us)
 | 
				
			||||||
 | 
					        return 0;               // No data to send
 | 
				
			||||||
 | 
					    if (!read_bit())            // Startbit(1)
 | 
				
			||||||
 | 
					        return -2;
 | 
				
			||||||
 | 
					    data = read_byte();
 | 
				
			||||||
 | 
					    data = (data<<8) | read_byte();
 | 
				
			||||||
 | 
					    if (read_bit())             // Stopbit(0)
 | 
				
			||||||
 | 
					        return -3;
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void data_lo()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ADB_DDR  |=  (1<<ADB_DATA_BIT);
 | 
				
			||||||
 | 
					    ADB_PORT &= ~(1<<ADB_DATA_BIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void data_hi()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ADB_PORT |=  (1<<ADB_DATA_BIT);
 | 
				
			||||||
 | 
					    ADB_DDR  &= ~(1<<ADB_DATA_BIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline bool data_in()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ADB_PORT |=  (1<<ADB_DATA_BIT);
 | 
				
			||||||
 | 
					    ADB_DDR  &= ~(1<<ADB_DATA_BIT);
 | 
				
			||||||
 | 
					    return ADB_PIN&(1<<ADB_DATA_BIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ADB_PSW_BIT
 | 
				
			||||||
 | 
					static inline void psw_lo()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ADB_DDR  |=  (1<<ADB_PSW_BIT);
 | 
				
			||||||
 | 
					    ADB_PORT &= ~(1<<ADB_PSW_BIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void psw_hi()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ADB_PORT |=  (1<<ADB_PSW_BIT);
 | 
				
			||||||
 | 
					    ADB_DDR  &= ~(1<<ADB_PSW_BIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline bool psw_in()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ADB_PORT |=  (1<<ADB_PSW_BIT);
 | 
				
			||||||
 | 
					    ADB_DDR  &= ~(1<<ADB_PSW_BIT);
 | 
				
			||||||
 | 
					    return ADB_PIN&(1<<ADB_PSW_BIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void attention(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    data_lo();
 | 
				
			||||||
 | 
					    _delay_us(700);
 | 
				
			||||||
 | 
					    place_bit1();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void place_bit0(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    data_lo();
 | 
				
			||||||
 | 
					    _delay_us(65);
 | 
				
			||||||
 | 
					    data_hi();
 | 
				
			||||||
 | 
					    _delay_us(35);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void place_bit1(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    data_lo();
 | 
				
			||||||
 | 
					    _delay_us(35);
 | 
				
			||||||
 | 
					    data_hi();
 | 
				
			||||||
 | 
					    _delay_us(65);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void send_byte(uint8_t data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    for (int i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
					        if (data&(0x80>>i))
 | 
				
			||||||
 | 
					            place_bit1();
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            place_bit0();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool read_bit(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // ADB Bit Cells
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // bit0: ______~~~
 | 
				
			||||||
 | 
					    //       65    :35us
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // bit1: ___~~~~~~
 | 
				
			||||||
 | 
					    //       35 :65us
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // bit0 low time: 60-70% of bit cell(42-91us)
 | 
				
			||||||
 | 
					    // bit1 low time: 30-40% of bit cell(21-52us)
 | 
				
			||||||
 | 
					    // bit cell time: 70-130us
 | 
				
			||||||
 | 
					    // [from Apple IIgs Hardware Reference Second Edition]
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // After 55us if data line is low/high then bit is 0/1.
 | 
				
			||||||
 | 
					    // Too simple to rely on?
 | 
				
			||||||
 | 
					    bool bit;
 | 
				
			||||||
 | 
					    wait_data_lo(75);   // wait the beginning of bit cell
 | 
				
			||||||
 | 
					    _delay_us(55);
 | 
				
			||||||
 | 
					    bit = data_in();
 | 
				
			||||||
 | 
					    wait_data_hi(36);   // wait high part of bit cell
 | 
				
			||||||
 | 
					    return bit;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint8_t read_byte(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t data = 0;
 | 
				
			||||||
 | 
					    for (int i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
					        data <<= 1;
 | 
				
			||||||
 | 
					        if (read_bit())
 | 
				
			||||||
 | 
					            data = data | 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint8_t wait_data_lo(uint8_t us)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    while (data_in() && us) {
 | 
				
			||||||
 | 
					        _delay_us(1);
 | 
				
			||||||
 | 
					        us--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return us;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint8_t wait_data_hi(uint8_t us)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    while (!data_in() && us) {
 | 
				
			||||||
 | 
					        _delay_us(1);
 | 
				
			||||||
 | 
					        us--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return us;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								adb.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								adb.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					#ifndef ADB_H
 | 
				
			||||||
 | 
					#define ADB_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !(defined(ADB_PORT) && \
 | 
				
			||||||
 | 
					      defined(ADB_PIN)  && \
 | 
				
			||||||
 | 
					      defined(ADB_DDR)  && \
 | 
				
			||||||
 | 
					      defined(ADB_DATA_BIT))
 | 
				
			||||||
 | 
					#   error "ADB port setting is required in config.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ADB host
 | 
				
			||||||
 | 
					void     adb_host_init(void);
 | 
				
			||||||
 | 
					bool     adb_host_psw(void);
 | 
				
			||||||
 | 
					uint16_t adb_host_kbd_recv(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										82
									
								
								adb/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								adb/Makefile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					# Hey Emacs, this is a -*- makefile -*-
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Released to the Public Domain
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Additional material for this makefile was written by:
 | 
				
			||||||
 | 
					# Peter Fleury
 | 
				
			||||||
 | 
					# Tim Henigan
 | 
				
			||||||
 | 
					# Colin O'Flynn
 | 
				
			||||||
 | 
					# Reiner Patommel
 | 
				
			||||||
 | 
					# Markus Pfaff
 | 
				
			||||||
 | 
					# Sander Pool
 | 
				
			||||||
 | 
					# Frederik Rouleau
 | 
				
			||||||
 | 
					# Carlos Lamas
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# On command line:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make all = Make software.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make clean = Clean out built project files.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make coff = Convert ELF to AVR COFF.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make extcoff = Convert ELF to AVR Extended COFF.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make program = Download the hex file to the device, using avrdude.
 | 
				
			||||||
 | 
					#                Please customize the avrdude settings below first!
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make debug = Start either simulavr or avarice as specified for debugging, 
 | 
				
			||||||
 | 
					#              with avr-gdb or avr-insight as the front end for debugging.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make filename.s = Just compile filename.c into the assembler code only.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# make filename.i = Create a preprocessed source file for use in submitting
 | 
				
			||||||
 | 
					#                   bug reports to the GCC project.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To rebuild project do "make clean" then "make all".
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Target file name (without extension).
 | 
				
			||||||
 | 
					TARGET = tmk_adb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Directory common source filess exist
 | 
				
			||||||
 | 
					COMMON_DIR = ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Directory keyboard dependent files exist
 | 
				
			||||||
 | 
					TARGET_DIR = .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# keyboard dependent files
 | 
				
			||||||
 | 
					TARGET_SRC =	keymap.c \
 | 
				
			||||||
 | 
					  	        matrix.c \
 | 
				
			||||||
 | 
							adb.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# MCU name, you MUST set this to match the board you are using
 | 
				
			||||||
 | 
					# type "make clean" after changing this, so all files will be rebuilt
 | 
				
			||||||
 | 
					#MCU = at90usb162       # Teensy 1.0
 | 
				
			||||||
 | 
					MCU = atmega32u4       # Teensy 2.0
 | 
				
			||||||
 | 
					#MCU = at90usb646       # Teensy++ 1.0
 | 
				
			||||||
 | 
					#MCU = at90usb1286      # Teensy++ 2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Processor frequency.
 | 
				
			||||||
 | 
					#   Normally the first thing your program should do is set the clock prescaler,
 | 
				
			||||||
 | 
					#   so your program will run at the correct speed.  You should also set this
 | 
				
			||||||
 | 
					#   variable to same clock speed.  The _delay_ms() macro uses this, and many
 | 
				
			||||||
 | 
					#   examples use this variable to calculate timings.  Do not add a "UL" here.
 | 
				
			||||||
 | 
					F_CPU = 16000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build Options
 | 
				
			||||||
 | 
					#   comment out to disable the options.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					MOUSEKEY_ENABLE = yes	# Mouse keys
 | 
				
			||||||
 | 
					#PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support
 | 
				
			||||||
 | 
					USB_EXTRA_ENABLE = yes	# Enhanced feature for Windows(Audio control and System control)
 | 
				
			||||||
 | 
					#USB_NKRO_ENABLE = yes	# USB Nkey Rollover
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(COMMON_DIR)/Makefile.common
 | 
				
			||||||
							
								
								
									
										19
									
								
								adb/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								adb/README
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					ADB to USB keyboard converter
 | 
				
			||||||
 | 
					=============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This firmware converts ADB keyboard protocol to USB.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Build
 | 
				
			||||||
 | 
					-----
 | 
				
			||||||
 | 
					0. Connect ADB keyboard to Teensy by 3 lines(Vcc, GND, Data).
 | 
				
			||||||
 | 
					   PSW line is optional. See ADB.txt for details.
 | 
				
			||||||
 | 
					1. Define following macros for ADB connection in config.h:
 | 
				
			||||||
 | 
					   ADB_PORT
 | 
				
			||||||
 | 
					   ADB_PIN
 | 
				
			||||||
 | 
					   ADB_DDR
 | 
				
			||||||
 | 
					   ADB_DATA_BIT
 | 
				
			||||||
 | 
					   ADB_PSW_BIT
 | 
				
			||||||
 | 
					2. make
 | 
				
			||||||
 | 
					3. program Teensy.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
							
								
								
									
										47
									
								
								adb/config.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								adb/config.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,47 @@
 | 
				
			||||||
 | 
					#ifndef CONFIG_H
 | 
				
			||||||
 | 
					#define CONFIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* controller configuration */
 | 
				
			||||||
 | 
					#include "controller_teensy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VENDOR_ID       0xFEED
 | 
				
			||||||
 | 
					#define PRODUCT_ID      0x0ADB
 | 
				
			||||||
 | 
					#define MANUFACTURER    t.m.k.
 | 
				
			||||||
 | 
					#define PRODUCT         ADB keyboard converter
 | 
				
			||||||
 | 
					#define DESCRIPTION     convert ADB keyboard to USB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* matrix size */
 | 
				
			||||||
 | 
					#define MATRIX_ROWS 16  // keycode bit: 3-0
 | 
				
			||||||
 | 
					#define MATRIX_COLS 8   // keycode bit: 6-4
 | 
				
			||||||
 | 
					/* define if matrix has ghost */
 | 
				
			||||||
 | 
					//#define MATRIX_HAS_GHOST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* USB NKey Rollover */
 | 
				
			||||||
 | 
					#ifdef USB_NKRO_ENABLE
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* mouse keys */
 | 
				
			||||||
 | 
					#ifdef MOUSEKEY_ENABLE
 | 
				
			||||||
 | 
					#   define MOUSEKEY_DELAY_TIME 192
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* PS/2 mouse */
 | 
				
			||||||
 | 
					#ifdef PS2_MOUSE_ENABLE
 | 
				
			||||||
 | 
					#   define PS2_CLOCK_PORT  PORTF
 | 
				
			||||||
 | 
					#   define PS2_CLOCK_PIN   PINF
 | 
				
			||||||
 | 
					#   define PS2_CLOCK_DDR   DDRF
 | 
				
			||||||
 | 
					#   define PS2_CLOCK_BIT   0
 | 
				
			||||||
 | 
					#   define PS2_DATA_PORT   PORTF
 | 
				
			||||||
 | 
					#   define PS2_DATA_PIN    PINF
 | 
				
			||||||
 | 
					#   define PS2_DATA_DDR    DDRF
 | 
				
			||||||
 | 
					#   define PS2_DATA_BIT    1
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ADB port setting */
 | 
				
			||||||
 | 
					#define ADB_PORT        PORTF
 | 
				
			||||||
 | 
					#define ADB_PIN         PINF
 | 
				
			||||||
 | 
					#define ADB_DDR         DDRF
 | 
				
			||||||
 | 
					#define ADB_DATA_BIT    0
 | 
				
			||||||
 | 
					//#define ADB_PSW_BIT     1       // optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										135
									
								
								adb/keymap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								adb/keymap.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,135 @@
 | 
				
			||||||
 | 
					/* 
 | 
				
			||||||
 | 
					 * Keymap for ADB keyboard
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <avr/pgmspace.h>
 | 
				
			||||||
 | 
					#include "usb_keyboard.h"
 | 
				
			||||||
 | 
					#include "usb_keycodes.h"
 | 
				
			||||||
 | 
					#include "print.h"
 | 
				
			||||||
 | 
					#include "debug.h"
 | 
				
			||||||
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					#include "keymap_skel.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert physical keyboard layout to matrix array.
 | 
				
			||||||
 | 
					// This is a macro to define keymap easily in keyboard layout form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: ADB to USB default keymap
 | 
				
			||||||
 | 
					// TODO: keymap macro template for m0116/m0115
 | 
				
			||||||
 | 
					/* Apple Keyboard m0116
 | 
				
			||||||
 | 
					    K7F, \
 | 
				
			||||||
 | 
					    K35, K12, K13, K14, K15, K17, K16, K1A, K1C, K19, K1D, K1B, K18, K33,       K47, K51, K4B, K43, \
 | 
				
			||||||
 | 
					    K30, K0C, K0D, K0E, K0F, K10, K11, K20, K22, K1F, K23, K21, K1E,            K59, K5B, K5C, K4E, \
 | 
				
			||||||
 | 
					    K36, K00, K01, K02, K03, K05, K04, K26, K28, K25, K29, K27,      K24,       K56, K57, K58, K45, \
 | 
				
			||||||
 | 
					    K38, K06, K07, K08, K09, K0B, K2D, K2E, K2B, K2F, K2C,           K7B,       K53, K54, K55,      \
 | 
				
			||||||
 | 
					    K39, K3A, K37, K32,           K31,           K2A, K3B, K3C, K3D, K3E,       K52,      K41, K4C  \
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* no tenkey
 | 
				
			||||||
 | 
					    K7F, \
 | 
				
			||||||
 | 
					    K35, K12, K13, K14, K15, K17, K16, K1A, K1C, K19, K1D, K1B, K18, K33, \
 | 
				
			||||||
 | 
					    K30, K0C, K0D, K0E, K0F, K10, K11, K20, K22, K1F, K23, K21, K1E,      \
 | 
				
			||||||
 | 
					    K36, K00, K01, K02, K03, K05, K04, K26, K28, K25, K29, K27,      K24, \
 | 
				
			||||||
 | 
					    K38, K06, K07, K08, K09, K0B, K2D, K2E, K2B, K2F, K2C,           K7B, \
 | 
				
			||||||
 | 
					    K39, K3A, K37, K32,           K31,           K2A, K3B, K3C, K3D, K3E \
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#define KEYMAP( \
 | 
				
			||||||
 | 
					    K7F, \
 | 
				
			||||||
 | 
					    K35, K12, K13, K14, K15, K17, K16, K1A, K1C, K19, K1D, K1B, K18, K33, \
 | 
				
			||||||
 | 
					    K30, K0C, K0D, K0E, K0F, K10, K11, K20, K22, K1F, K23, K21, K1E,      \
 | 
				
			||||||
 | 
					    K36, K00, K01, K02, K03, K05, K04, K26, K28, K25, K29, K27,      K24, \
 | 
				
			||||||
 | 
					    K38, K06, K07, K08, K09, K0B, K2D, K2E, K2B, K2F, K2C,           K7B, \
 | 
				
			||||||
 | 
					    K39, K3A, K37, K32,           K31,           K2A, K3B, K3C, K3D, K3E  \
 | 
				
			||||||
 | 
					) { \
 | 
				
			||||||
 | 
					    { K00, K01, K02, K03, K04, K05, K06,  K07 }, \
 | 
				
			||||||
 | 
					    { K08, K09, 000, K0B, K0C, K0D, K0E,  K0F }, \
 | 
				
			||||||
 | 
					    { K10, K11, K12, K13, K14, K15, K16,  K17 }, \
 | 
				
			||||||
 | 
					    { K18, K19, K1A, K1B, K1C, K1D, K1E,  K1F }, \
 | 
				
			||||||
 | 
					    { K20, K21, K22, K23, K24, K25, K26,  K27 }, \
 | 
				
			||||||
 | 
					    { K28, K29, K2A, K2B, K2C, K2D, K2E,  K2F }, \
 | 
				
			||||||
 | 
					    { K30, K31, K32, K33, 000, K35, K36,  K37 }, \
 | 
				
			||||||
 | 
					    { K38, K39, K3A, K3B, K3C, K3D, K3E,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, 000, 000, 000, 000,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, 000, 000, 000, 000,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, 000, 000, 000, 000,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, 000, 000, 000, 000,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, 000, 000, 000, 000,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, 000, 000, 000, 000,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, 000, 000, 000, 000,  000 }, \
 | 
				
			||||||
 | 
					    { 000, 000, 000, K7B, 000, 000, 000,  K7F }, \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
 | 
				
			||||||
 | 
					static const uint8_t PROGMEM fn_layer[] = {
 | 
				
			||||||
 | 
					    0,              // FN_0
 | 
				
			||||||
 | 
					    0,              // FN_1
 | 
				
			||||||
 | 
					    0,              // FN_2
 | 
				
			||||||
 | 
					    0,              // FN_3
 | 
				
			||||||
 | 
					    0,              // FN_4
 | 
				
			||||||
 | 
					    0,              // FN_5
 | 
				
			||||||
 | 
					    0,              // FN_6
 | 
				
			||||||
 | 
					    0               // FN_7
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer.
 | 
				
			||||||
 | 
					// See layer.c for details.
 | 
				
			||||||
 | 
					static const uint8_t PROGMEM fn_keycode[] = {
 | 
				
			||||||
 | 
					    KB_NO,          // FN_0
 | 
				
			||||||
 | 
					    KB_NO,          // FN_1
 | 
				
			||||||
 | 
					    KB_NO,          // FN_2
 | 
				
			||||||
 | 
					    KB_NO,          // FN_3
 | 
				
			||||||
 | 
					    KB_NO,          // FN_4
 | 
				
			||||||
 | 
					    KB_NO,          // FN_5
 | 
				
			||||||
 | 
					    KB_NO,          // FN_6
 | 
				
			||||||
 | 
					    KB_NO           // FN_7
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
				
			||||||
 | 
					    /* Layer 0: Default Layer
 | 
				
			||||||
 | 
					     * ,---------------------------------------------------------.
 | 
				
			||||||
 | 
					     * |Esc|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backs|
 | 
				
			||||||
 | 
					     * |---------------------------------------------------------|
 | 
				
			||||||
 | 
					     * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|   |
 | 
				
			||||||
 | 
					     * |-----------------------------------------------------'   |
 | 
				
			||||||
 | 
					     * |Contro|  A|  S|  D|  F|  G|  H|  J|  K|  L|Fn3|  '|Return|
 | 
				
			||||||
 | 
					     * |---------------------------------------------------------|
 | 
				
			||||||
 | 
					     * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|Shift   |
 | 
				
			||||||
 | 
					     * |---------------------------------------------------------|
 | 
				
			||||||
 | 
					     * |Shi|Alt|Gui   l  `|                  |  \|Lef|Rig|Dow|Up |
 | 
				
			||||||
 | 
					     * `---------------------------------------------------------'
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    KEYMAP(KB_PWR, \
 | 
				
			||||||
 | 
					           KB_ESC, KB_1,   KB_2,   KB_3,   KB_4,   KB_5,   KB_6,   KB_7,   KB_8,   KB_9,   KB_0,   KB_MINS,KB_EQL, KB_BSPC, \
 | 
				
			||||||
 | 
					           KB_TAB, KB_Q,   KB_W,   KB_E,   KB_R,   KB_T,   KB_Y,   KB_U,   KB_I,   KB_O,   KB_P,   KB_LBRC,KB_RBRC, \
 | 
				
			||||||
 | 
					           KB_LCTL,KB_A,   KB_S,   KB_D,   KB_F,   KB_G,   KB_H,   KB_J,   KB_K,   KB_L,   KB_SCLN,KB_QUOT,KB_ENT, \
 | 
				
			||||||
 | 
					           KB_LSFT,KB_Z,   KB_X,   KB_C,   KB_V,   KB_B,   KB_N,   KB_M,   KB_COMM,KB_DOT, KB_SLSH,KB_RSFT, \
 | 
				
			||||||
 | 
					           KB_LSFT,KB_LALT,KB_LGUI,KB_GRV, KB_SPC, KB_BSLS,KB_LEFT,KB_RGHT,KB_DOWN,KB_UP),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return KEYCODE(layer, row, col);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t keymap_fn_layer(uint8_t fn_bits)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return pgm_read_byte(&fn_layer[biton(fn_bits)]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t keymap_fn_keycode(uint8_t fn_bits)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// define a condition to enter special function mode
 | 
				
			||||||
 | 
					bool keymap_is_special_mode(uint8_t fn_bits)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));
 | 
				
			||||||
 | 
					    return (usb_keyboard_mods == (BIT_RSHIFT));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										194
									
								
								adb/matrix.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								adb/matrix.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,194 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * scan matrix
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <avr/io.h>
 | 
				
			||||||
 | 
					#include <util/delay.h>
 | 
				
			||||||
 | 
					#include "print.h"
 | 
				
			||||||
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					#include "debug.h"
 | 
				
			||||||
 | 
					#include "adb.h"
 | 
				
			||||||
 | 
					#include "matrix_skel.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if (MATRIX_COLS > 16)
 | 
				
			||||||
 | 
					#   error "MATRIX_COLS must not exceed 16"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if (MATRIX_ROWS > 255)
 | 
				
			||||||
 | 
					#   error "MATRIX_ROWS must not exceed 255"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool _matrix_is_modified = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// matrix state buffer(1:on, 0:off)
 | 
				
			||||||
 | 
					#if (MATRIX_COLS <= 8)
 | 
				
			||||||
 | 
					static uint8_t *matrix;
 | 
				
			||||||
 | 
					static uint8_t _matrix0[MATRIX_ROWS];
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static uint16_t *matrix;
 | 
				
			||||||
 | 
					static uint16_t _matrix0[MATRIX_ROWS];
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef MATRIX_HAS_GHOST
 | 
				
			||||||
 | 
					static bool matrix_has_ghost_in_row(uint8_t row);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					static void _register_key(uint8_t key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					uint8_t matrix_rows(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return MATRIX_ROWS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					uint8_t matrix_cols(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return MATRIX_COLS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void matrix_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    adb_host_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initialize matrix state: all keys off
 | 
				
			||||||
 | 
					    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
 | 
				
			||||||
 | 
					    matrix = _matrix0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print_enable = true;
 | 
				
			||||||
 | 
					    debug_enable = true;
 | 
				
			||||||
 | 
					    debug_matrix = true;
 | 
				
			||||||
 | 
					    debug_keyboard = true;
 | 
				
			||||||
 | 
					    debug_mouse = true;
 | 
				
			||||||
 | 
					    print("debug enabled.\n");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t matrix_scan(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t codes;
 | 
				
			||||||
 | 
					    uint8_t key0, key1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _matrix_is_modified = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    codes = adb_host_kbd_recv();
 | 
				
			||||||
 | 
					    key0 = codes>>8;
 | 
				
			||||||
 | 
					    key1 = codes&0xFF;
 | 
				
			||||||
 | 
					    if (debug_matrix) {
 | 
				
			||||||
 | 
					        //print("adb_host_kbd_recv: "); phex16(codes); print("\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (codes == 0) {                           // no keys
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    } else if (key0 == 0xFF && key1 != 0xFF) {  // error
 | 
				
			||||||
 | 
					        return codes&0xFF;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        _matrix_is_modified = true;
 | 
				
			||||||
 | 
					        _register_key(key0);
 | 
				
			||||||
 | 
					        if (key1 != 0xFF)       // key1 is 0xFF when no second key.
 | 
				
			||||||
 | 
					            _register_key(key1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool matrix_is_modified(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return _matrix_is_modified;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					bool matrix_has_ghost(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef MATRIX_HAS_GHOST
 | 
				
			||||||
 | 
					    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
 | 
				
			||||||
 | 
					        if (matrix_has_ghost_in_row(i))
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					bool matrix_is_on(uint8_t row, uint8_t col)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (matrix[row] & (1<<col));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					#if (MATRIX_COLS <= 8)
 | 
				
			||||||
 | 
					uint8_t matrix_get_row(uint8_t row)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					uint16_t matrix_get_row(uint8_t row)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return matrix[row];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void matrix_print(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if (MATRIX_COLS <= 8)
 | 
				
			||||||
 | 
					    print("\nr/c 01234567\n");
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    print("\nr/c 0123456789ABCDEF\n");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    for (uint8_t row = 0; row < matrix_rows(); row++) {
 | 
				
			||||||
 | 
					        phex(row); print(": ");
 | 
				
			||||||
 | 
					#if (MATRIX_COLS <= 8)
 | 
				
			||||||
 | 
					        pbin_reverse(matrix_get_row(row));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					        pbin_reverse16(matrix_get_row(row));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef MATRIX_HAS_GHOST
 | 
				
			||||||
 | 
					        if (matrix_has_ghost_in_row(row)) {
 | 
				
			||||||
 | 
					            print(" <ghost");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        print("\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t matrix_key_count(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t count = 0;
 | 
				
			||||||
 | 
					    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
 | 
				
			||||||
 | 
					#if (MATRIX_COLS <= 8)
 | 
				
			||||||
 | 
					        count += bitpop(matrix[i]);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					        count += bitpop16(matrix[i]);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef MATRIX_HAS_GHOST
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					static bool matrix_has_ghost_in_row(uint8_t row)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // no ghost exists in case less than 2 keys on
 | 
				
			||||||
 | 
					    if (((matrix[row] - 1) & matrix[row]) == 0)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ghost exists in case same state as other row
 | 
				
			||||||
 | 
					    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
 | 
				
			||||||
 | 
					        if (i != row && (matrix[i] & matrix[row]) == matrix[row])
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline
 | 
				
			||||||
 | 
					static void _register_key(uint8_t key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t col, row;
 | 
				
			||||||
 | 
					    col = key&0x07;
 | 
				
			||||||
 | 
					    row = (key>>3)&0x0F;
 | 
				
			||||||
 | 
					    if (key&0x80) {
 | 
				
			||||||
 | 
					        matrix[row] &= ~(1<<col);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        matrix[row] |=  (1<<col);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue