Squashed 'tmk_core/' changes from b9e0ea0..caca2c0

caca2c0 Add mouse support to ADB
5b0835a Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
f2f7556 Remove unneeded tap delays #201
8124195 Fix URL of HID Usage Tables pdf
0bb4679 Fix typo of doc/keycode.txt
b24fa1a Fix handling of consumer usage #199
6ae1a3d Improve anti-ghosting behavior for fast typing
a4c9763 Fix dfu-programmer parameters
b62b3f2 Move ring_buffer.h file
6ec424f Fix debug print
502fb0c Fix ibm4704 protocol with using interrupt

git-subtree-dir: tmk_core
git-subtree-split: caca2c01553394d959550034c817520d575c7fa0
example_keyboards
tmk 10 years ago
parent 1fe4406f37
commit 4d116a04e9

@ -518,7 +518,12 @@ bool is_tap_key(keypos_t key)
case ACT_RMODS_TAP: case ACT_RMODS_TAP:
case ACT_LAYER_TAP: case ACT_LAYER_TAP:
case ACT_LAYER_TAP_EXT: case ACT_LAYER_TAP_EXT:
switch (action.layer_tap.code) {
case 0x00 ... 0xdf:
case OP_TAP_TOGGLE:
return true; return true;
}
return false;
case ACT_MACRO: case ACT_MACRO:
case ACT_FUNCTION: case ACT_FUNCTION:
if (action.func.opt & FUNC_TAP) { return true; } if (action.func.opt & FUNC_TAP) { return true; }

@ -70,13 +70,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* 1001|oopp|BBBB BBBB 8-bit Bitwise Operation??? * 1001|oopp|BBBB BBBB 8-bit Bitwise Operation???
* *
* ACT_LAYER_TAP(101x): * ACT_LAYER_TAP(101x):
* 101E|LLLL| keycode On/Off with tap key * 101E|LLLL| keycode On/Off with tap key (0x00-DF)[TAP]
* 101E|LLLL|1110 mods On/Off with modifiers(0xE0-EF) * 101E|LLLL|1110 mods On/Off with modifiers (0xE0-EF)[NOT TAP]
* 101E|LLLL|1111 0000 Invert with tap toggle(0xF0) * 101E|LLLL|1111 0000 Invert with tap toggle (0xF0) [TAP]
* 101E|LLLL|1111 0001 On/Off * 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP]
* 101E|LLLL|1111 0010 Off/On * 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP]
* 101E|LLLL|1111 0011 Set/Clear * 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP]
* 101E|LLLL|1111 xxxx Reserved(0xF4-FF) * 101E|LLLL|1111 xxxx Reserved (0xF4-FF)
* ELLLL: layer 0-31(E: extra bit for layer 16-31) * ELLLL: layer 0-31(E: extra bit for layer 16-31)
* *
* *

@ -39,6 +39,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef SERIAL_MOUSE_ENABLE #ifdef SERIAL_MOUSE_ENABLE
#include "serial_mouse.h" #include "serial_mouse.h"
#endif #endif
#ifdef ADB_MOUSE_ENABLE
#include "adb.h"
#endif
#ifdef MATRIX_HAS_GHOST #ifdef MATRIX_HAS_GHOST
@ -69,6 +72,9 @@ void keyboard_init(void)
#ifdef SERIAL_MOUSE_ENABLE #ifdef SERIAL_MOUSE_ENABLE
serial_mouse_init(); serial_mouse_init();
#endif #endif
#ifdef ADB_MOUSE_ENABLE
adb_mouse_init();
#endif
#ifdef BOOTMAGIC_ENABLE #ifdef BOOTMAGIC_ENABLE
@ -87,6 +93,9 @@ void keyboard_init(void)
void keyboard_task(void) void keyboard_task(void)
{ {
static matrix_row_t matrix_prev[MATRIX_ROWS]; static matrix_row_t matrix_prev[MATRIX_ROWS];
#ifdef MATRIX_HAS_GHOST
static matrix_row_t matrix_ghost[MATRIX_ROWS];
#endif
static uint8_t led_status = 0; static uint8_t led_status = 0;
matrix_row_t matrix_row = 0; matrix_row_t matrix_row = 0;
matrix_row_t matrix_change = 0; matrix_row_t matrix_change = 0;
@ -96,13 +105,21 @@ void keyboard_task(void)
matrix_row = matrix_get_row(r); matrix_row = matrix_get_row(r);
matrix_change = matrix_row ^ matrix_prev[r]; matrix_change = matrix_row ^ matrix_prev[r];
if (matrix_change) { if (matrix_change) {
if (debug_matrix) matrix_print();
#ifdef MATRIX_HAS_GHOST #ifdef MATRIX_HAS_GHOST
if (has_ghost_in_row(r)) { if (has_ghost_in_row(r)) {
matrix_prev[r] = matrix_row; /* Keep track of whether ghosted status has changed for
* debugging. But don't update matrix_prev until un-ghosted, or
* the last key would be lost.
*/
if (debug_matrix && matrix_ghost[r] != matrix_row) {
matrix_print();
}
matrix_ghost[r] = matrix_row;
continue; continue;
} }
matrix_ghost[r] = matrix_row;
#endif #endif
if (debug_matrix) matrix_print();
for (uint8_t c = 0; c < MATRIX_COLS; c++) { for (uint8_t c = 0; c < MATRIX_COLS; c++) {
if (matrix_change & ((matrix_row_t)1<<c)) { if (matrix_change & ((matrix_row_t)1<<c)) {
action_exec((keyevent_t){ action_exec((keyevent_t){
@ -136,6 +153,10 @@ MATRIX_LOOP_END:
serial_mouse_task(); serial_mouse_task();
#endif #endif
#ifdef ADB_MOUSE_ENABLE
adb_mouse_task();
#endif
// update LED // update LED
if (led_status != host_keyboard_leds()) { if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds(); led_status = host_keyboard_leds();

@ -131,7 +131,7 @@ static action_t keycode_to_action(uint8_t keycode)
case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode)); action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
break; break;
case KC_AUDIO_MUTE ... KC_WWW_FAVORITES: case KC_AUDIO_MUTE ... KC_MEDIA_REWIND:
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode)); action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
break; break;
case KC_MS_UP ... KC_MS_ACCEL2: case KC_MS_UP ... KC_MS_ACCEL2:

@ -174,7 +174,7 @@ KC_CLEAR_AGAIN A2 Keyboard Clear/Again
KC_CRSEL A3 Keyboard CrSel/Props KC_CRSEL A3 Keyboard CrSel/Props
KC_EXSEL A4 Keyboard ExSel KC_EXSEL A4 Keyboard ExSel
/* Modifiers */ /* Modifiers */
KC_LCTRL KC_LCTRL E0 Keyboard LeftControl KC_LCTRL KC_LCTL E0 Keyboard LeftControl
KC_LSHIFT KC_LSFT E1 Keyboard LeftShift KC_LSHIFT KC_LSFT E1 Keyboard LeftShift
KC_LALT E2 Keyboard LeftAlt KC_LALT E2 Keyboard LeftAlt
KC_LGUI E3 Keyboard Left GUI(Windows/Apple/Meta key) KC_LGUI E3 Keyboard Left GUI(Windows/Apple/Meta key)

@ -198,7 +198,7 @@ There are 8 modifiers which has discrimination between left and right.
See keycode table in [`doc/keycode.txt`](./keycode.txt) for description of keycodes. See keycode table in [`doc/keycode.txt`](./keycode.txt) for description of keycodes.
In regard to implementation side most of keycodes are identical with [HID usage][HID_usage](pdf) sent to host for real and some virtual keycodes are defined to support special actions. In regard to implementation side most of keycodes are identical with [HID usage][HID_usage](pdf) sent to host for real and some virtual keycodes are defined to support special actions.
[HID_usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf [HID_usage]: http://www.usb.org/developers/hidpage/Hut1_12v2.pdf

@ -46,5 +46,9 @@ ifdef SERIAL_MOUSE_USE_UART
SRC += $(PROTOCOL_DIR)/serial_uart.c SRC += $(PROTOCOL_DIR)/serial_uart.c
endif endif
ifdef ADB_MOUSE_ENABLE
OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE
endif
# Search Path # Search Path
VPATH += $(TMK_DIR)/protocol VPATH += $(TMK_DIR)/protocol

@ -60,6 +60,7 @@ 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)
@ -121,12 +122,33 @@ bool adb_host_psw(void)
// //
// [from Apple IIgs Hardware Reference Second Edition] // [from Apple IIgs Hardware Reference Second Edition]
enum {
ADDR_KEYB = 0x20,
ADDR_MOUSE = 0x30
};
uint16_t adb_host_kbd_recv(void) uint16_t adb_host_kbd_recv(void)
{
return adb_host_dev_recv(ADDR_KEYB);
}
#ifdef ADB_MOUSE_ENABLE
void adb_mouse_init(void) {
return;
}
uint16_t adb_host_mouse_recv(void)
{
return adb_host_dev_recv(ADDR_MOUSE);
}
#endif
static inline uint16_t adb_host_dev_recv(uint8_t device)
{ {
uint16_t data = 0; uint16_t data = 0;
cli(); cli();
attention(); attention();
send_byte(0x2C); // Addr:Keyboard(0010), Cmd:Talk(11), Register0(00) send_byte(device|0x0C); // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00)
place_bit0(); // Stopbit(0) place_bit0(); // Stopbit(0)
if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
sei(); sei();

@ -56,7 +56,11 @@ POSSIBILITY OF SUCH DAMAGE.
void adb_host_init(void); void adb_host_init(void);
bool adb_host_psw(void); bool adb_host_psw(void);
uint16_t adb_host_kbd_recv(void); 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_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l);
void adb_host_kbd_led(uint8_t led); void adb_host_kbd_led(uint8_t led);
void adb_mouse_task(void);
void adb_mouse_init(void);
#endif #endif

@ -4,6 +4,7 @@ Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
#include <stdbool.h> #include <stdbool.h>
#include <util/delay.h> #include <util/delay.h>
#include "debug.h" #include "debug.h"
#include "ring_buffer.h"
#include "ibm4704.h" #include "ibm4704.h"
@ -20,7 +21,9 @@ uint8_t ibm4704_error = 0;
void ibm4704_init(void) void ibm4704_init(void)
{ {
inhibit(); IBM4704_INT_INIT();
IBM4704_INT_ON();
idle();
} }
/* /*
@ -47,6 +50,8 @@ uint8_t ibm4704_send(uint8_t data)
bool parity = true; // odd parity bool parity = true; // odd parity
ibm4704_error = 0; ibm4704_error = 0;
IBM4704_INT_OFF();
/* Request to send */ /* Request to send */
idle(); idle();
clock_lo(); clock_lo();
@ -57,7 +62,6 @@ uint8_t ibm4704_send(uint8_t data)
/* Data bit */ /* Data bit */
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
WAIT(clock_hi, 100, 0x40+i); WAIT(clock_hi, 100, 0x40+i);
//_delay_us(5);
if (data&(1<<i)) { if (data&(1<<i)) {
parity = !parity; parity = !parity;
data_hi(); data_hi();
@ -79,28 +83,25 @@ uint8_t ibm4704_send(uint8_t data)
/* End */ /* End */
WAIT(data_lo, 100, 0x36); WAIT(data_lo, 100, 0x36);
inhibit(); idle();
_delay_us(200); // wait to recover clock to hi IBM4704_INT_ON();
return 0; return 0;
ERROR: ERROR:
inhibit(); idle();
if (ibm4704_error >= 0x30) { if (ibm4704_error > 0x30) {
xprintf("x%02X ", ibm4704_error); xprintf("S:%02X ", ibm4704_error);
} }
_delay_us(200); // wait to recover clock to hi IBM4704_INT_ON();
return -1; return -1;
} }
/* receive data when host want else inhibit communication */ /* wait forever to receive data */
uint8_t ibm4704_recv_response(void) uint8_t ibm4704_recv_response(void)
{ {
// 250 * 100us(wait start bit in ibm4704_recv) while (!rbuf_has_data()) {
uint8_t data = 0; _delay_ms(1);
uint8_t try = 250; }
do { return rbuf_dequeue();
data = ibm4704_recv();
} while (try-- && ibm4704_error);
return data;
} }
/* /*
@ -121,49 +122,69 @@ Stop bit: Keyboard pulls down Data line to lo after 9th clock.
*/ */
uint8_t ibm4704_recv(void) uint8_t ibm4704_recv(void)
{ {
uint8_t data = 0; if (rbuf_has_data()) {
bool parity = true; // odd parity return rbuf_dequeue();
ibm4704_error = IBM4704_ERR_NONE; } else {
return -1;
idle(); }
_delay_us(5); // wait for line settles }
/* start bit */ ISR(IBM4704_INT_VECT)
WAIT(clock_lo, 100, 0x11); // wait for keyboard to send {
WAIT(data_hi, 100, 0x12); // can be delayed that long static enum {
INIT, START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY,
} state = INIT;
// LSB first
static uint8_t data = 0;
// Odd parity
static uint8_t parity = false;
WAIT(clock_hi, 100, 0x13); // first rising edge which can take longer ibm4704_error = 0;
/* data */ // return unless falling edge
for (uint8_t i = 0; i < 8; i++) { if (clock_in()) { goto RETURN; } // why this occurs?
WAIT(clock_hi, 100, 0x20+i);
//_delay_us(5); state++;
switch (state) {
case START:
// Data:Low
WAIT(data_hi, 10, state);
break;
case BIT0:
case BIT1:
case BIT2:
case BIT3:
case BIT4:
case BIT5:
case BIT6:
case BIT7:
data >>= 1;
if (data_in()) { if (data_in()) {
data |= 0x80;
parity = !parity; parity = !parity;
data |= (1<<i);
} }
WAIT(clock_lo, 150, 0x28+i); break;
case PARITY:
if (data_in()) {
parity = !parity;
} }
if (!parity)
/* parity */ goto ERROR;
WAIT(clock_hi, 100, 0x17); rbuf_enqueue(data);
if (data_in() != parity) { ibm4704_error = IBM4704_ERR_NONE;
ibm4704_error = IBM4704_ERR_PARITY; goto DONE;
break;
default:
goto ERROR; goto ERROR;
} }
WAIT(clock_lo, 150, 0x18); goto RETURN;
/* stop bit */
WAIT(clock_hi, 100, 0x19);
WAIT(data_lo, 1, 0x19);
inhibit();
_delay_us(200); // wait to recover clock to hi
return data;
ERROR: ERROR:
if (ibm4704_error > 0x12) { ibm4704_error = state;
xprintf("x%02X ", ibm4704_error); while (ibm4704_send(0xFE)) _delay_ms(1); // resend
} xprintf("R:%02X%02X\n", state, data);
inhibit(); DONE:
_delay_us(200); // wait to recover clock to hi state = INIT;
return -1; data = 0;
parity = false;
RETURN:
return;
} }

@ -11,6 +11,10 @@ ifdef MOUSEKEY_ENABLE
SRC += $(PJRC_DIR)/usb_mouse.c SRC += $(PJRC_DIR)/usb_mouse.c
endif endif
ifdef ADB_MOUSE_ENABLE
SRC += $(PJRC_DIR)/usb_mouse.c
endif
ifdef PS2_MOUSE_ENABLE ifdef PS2_MOUSE_ENABLE
SRC += $(PJRC_DIR)/usb_mouse.c SRC += $(PJRC_DIR)/usb_mouse.c
endif endif

@ -0,0 +1,53 @@
#ifndef RING_BUFFER_H
#define RING_BUFFER_H
/*--------------------------------------------------------------------
* Ring buffer to store scan codes from keyboard
*------------------------------------------------------------------*/
#define RBUF_SIZE 32
static uint8_t rbuf[RBUF_SIZE];
static uint8_t rbuf_head = 0;
static uint8_t rbuf_tail = 0;
static inline void rbuf_enqueue(uint8_t data)
{
uint8_t sreg = SREG;
cli();
uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
if (next != rbuf_tail) {
rbuf[rbuf_head] = data;
rbuf_head = next;
} else {
print("rbuf: full\n");
}
SREG = sreg;
}
static inline uint8_t rbuf_dequeue(void)
{
uint8_t val = 0;
uint8_t sreg = SREG;
cli();
if (rbuf_head != rbuf_tail) {
val = rbuf[rbuf_tail];
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
}
SREG = sreg;
return val;
}
static inline bool rbuf_has_data(void)
{
uint8_t sreg = SREG;
cli();
bool has_data = (rbuf_head != rbuf_tail);
SREG = sreg;
return has_data;
}
static inline void rbuf_clear(void)
{
uint8_t sreg = SREG;
cli();
rbuf_head = rbuf_tail = 0;
SREG = sreg;
}
#endif /* RING_BUFFER_H */

@ -440,7 +440,11 @@ flip-ee: $(TARGET).hex $(TARGET).eep
$(REMOVE) $(TARGET)eep.hex $(REMOVE) $(TARGET)eep.hex
dfu-ee: $(TARGET).hex $(TARGET).eep dfu-ee: $(TARGET).hex $(TARGET).eep
dfu-programmer $(MCU) eeprom-flash $(TARGET).eep ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
dfu-programmer $(MCU) flash --eeprom $(TARGET).eep
else
dfu-programmer $(MCU) flash-eeprom $(TARGET).eep
endif
dfu-programmer $(MCU) reset dfu-programmer $(MCU) reset

Loading…
Cancel
Save