From f5f48c2a240b43e1773c3787b8fca8859f128cf7 Mon Sep 17 00:00:00 2001 From: tmk Date: Tue, 15 May 2012 03:41:07 +0900 Subject: [PATCH] Fix bug on RAW2SCAN. Add work around for M0110A. - Bug fix: Macro RAW2SCAN doesn't work and converted into static inline function. - Add Exceptional handling for M0110A arrow keys and calc keys. - Fix keymap. --- m0110.c | 457 ++++++++++++++++++++------------------- m0110.h | 9 - m0110_usb/doc/m0110.jpg | Bin m0110_usb/doc/teensy.jpg | Bin m0110_usb/keymap.c | 90 ++++---- m0110_usb/matrix.c | 28 ++- rules.mk | 2 +- 7 files changed, 307 insertions(+), 279 deletions(-) mode change 100755 => 100644 m0110_usb/doc/m0110.jpg mode change 100755 => 100644 m0110_usb/doc/teensy.jpg diff --git a/m0110.c b/m0110.c index 20b4860a..638897ae 100644 --- a/m0110.c +++ b/m0110.c @@ -44,6 +44,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "debug.h" +static inline uint8_t raw2scan(uint8_t raw); static inline uint8_t inquiry(void); static inline uint8_t instant(void); static inline void clock_lo(void); @@ -60,6 +61,241 @@ static inline void idle(void); static inline void request(void); +#define WAIT_US(stat, us, err) do { \ + if (!wait_##stat(us)) { \ + m0110_error = err; \ + goto ERROR; \ + } \ +} while (0) + +#define WAIT_MS(stat, ms, err) do { \ + uint16_t _ms = ms; \ + while (_ms) { \ + if (wait_##stat(1000)) { \ + break; \ + } \ + _ms--; \ + } \ + if (_ms == 0) { \ + m0110_error = err; \ + goto ERROR; \ + } \ +} while (0) + + +uint8_t m0110_error = 0; + + +void m0110_init(void) +{ + uint8_t data; + idle(); + _delay_ms(1000); + + // Model Number + // M0110 : 0x09 00001001 : model number 4 (100) + // M0110A: 0x0B 00001011 : model number 5 (101) + // M0110 & M0120: ??? + m0110_send(M0110_MODEL); + data = m0110_recv(); + print("m0110_init model: "); phex(data); print("\n"); + + m0110_send(M0110_TEST); + data = m0110_recv(); + print("m0110_init test: "); phex(data); print("\n"); +} + +uint8_t m0110_send(uint8_t data) +{ + m0110_error = 0; + + request(); + WAIT_MS(clock_lo, 250, 1); // keyboard may block long time + for (uint8_t bit = 0x80; bit; bit >>= 1) { + WAIT_US(clock_lo, 250, 3); + if (data&bit) { + data_hi(); + } else { + data_lo(); + } + WAIT_US(clock_hi, 200, 4); + } + _delay_us(100); // hold last bit for 80us + idle(); + return 1; +ERROR: + print("m0110_send err: "); phex(m0110_error); print("\n"); + _delay_ms(500); + idle(); + return 0; +} + +uint8_t m0110_recv(void) +{ + uint8_t data = 0; + m0110_error = 0; + + WAIT_MS(clock_lo, 250, 1); // keyboard may block long time + for (uint8_t i = 0; i < 8; i++) { + data <<= 1; + WAIT_US(clock_lo, 200, 2); + WAIT_US(clock_hi, 200, 3); + if (data_in()) { + data |= 1; + } + } + idle(); + return data; +ERROR: + print("m0110_recv err: "); phex(m0110_error); print("\n"); + _delay_ms(500); + idle(); + return 0xFF; +} + +uint8_t m0110_recv_key(void) +{ + static uint8_t keybuf = 0x00; + uint8_t key, key2, key3; + + if (keybuf) { + key = keybuf; + keybuf = 0x00; + return key; + } + key = instant(); // Use INSTANT for better response. Should be INQUIRY ? + switch (key & 0x7F) { + case M0110_KEYPAD: + // Pad/Arrow keys + return (raw2scan(instant()) | M0110_KEYPAD_OFFSET); + break; + case M0110_SHIFT: + key2 = instant(); + if (key2 == M0110_KEYPAD) { + key3 = instant(); + switch (key3 & 0x7F) { + case M0110_ARROW_UP: + case M0110_ARROW_DOWN: + case M0110_ARROW_LEFT: + case M0110_ARROW_RIGHT: + // Calc keys + return (raw2scan(key3) | M0110_CALC_OFFSET); + default: + // Shift + Pad/Arrow keys + keybuf = raw2scan(key3); + return (raw2scan(key) | M0110_KEYPAD_OFFSET); + } + } else { + // Shift + other keys + keybuf = raw2scan(key2); + return raw2scan(key); + } + break; + default: + // other keys + return raw2scan(key); + break; + } +} + + +static inline uint8_t raw2scan(uint8_t raw) { + return (raw == M0110_NULL) ? M0110_NULL : ( + (raw == M0110_ERROR) ? M0110_ERROR : ( + ((raw&0x80) | ((raw&0x7F)>>1)) + ) + ); +} + +static inline uint8_t inquiry(void) +{ + m0110_send(M0110_INQUIRY); + return m0110_recv(); +} + +static inline uint8_t instant(void) +{ + m0110_send(M0110_INSTANT); + //return m0110_recv(); + uint8_t data = m0110_recv(); + if (data != 0x7B) { + print("data: "); phex(data); print("\n"); + } + return data; +} + +static inline void clock_lo() +{ + M0110_CLOCK_PORT &= ~(1<>= 1) { - WAIT_US(clock_lo, 250, 3); - if (data&bit) { - data_hi(); - } else { - data_lo(); - } - WAIT_US(clock_hi, 200, 4); - } - _delay_us(100); // hold last bit for 80us - idle(); - return 1; -ERROR: - print("m0110_send err: "); phex(m0110_error); print("\n"); - _delay_ms(500); - idle(); - return 0; -} - -uint8_t m0110_recv(void) -{ - uint8_t data = 0; - m0110_error = 0; - - WAIT_MS(clock_lo, 250, 1); // keyboard may block long time - for (uint8_t i = 0; i < 8; i++) { - data <<= 1; - WAIT_US(clock_lo, 200, 2); - WAIT_US(clock_hi, 200, 3); - if (data_in()) { - data |= 1; - } - } - idle(); - return data; -ERROR: - print("m0110_recv err: "); phex(m0110_error); print("\n"); - _delay_ms(500); - idle(); - return 0xFF; -} - -uint8_t m0110_recv_key(void) -{ - static uint8_t keybuf = 0x00; - uint8_t key, key2, key3; - - if (keybuf) { - key = keybuf; - keybuf = 0x00; - return key; - } - key = instant(); // Use INSTANT for better response. Should be INQUIRY ? - switch (key & 0x7F) { - case M0110_KEYPAD: - // Pad/Arrow keys - return (M0110_RAW2SCAN(instant()) | M0110_KEYPAD_OFFSET); - break; - case M0110_SHIFT: - key2 = instant(); - if (key2 == M0110_KEYPAD) { - key3 = instant(); - switch (key3 & 0x7F) { - case M0110_ARROW_UP: - case M0110_ARROW_DOWN: - case M0110_ARROW_LEFT: - case M0110_ARROW_RIGHT: - // Calc keys - return (M0110_RAW2SCAN(key3) | M0110_CALC_OFFSET); - default: - // Shift + Pad/Arrow keys - keybuf = M0110_RAW2SCAN(key3); - return (M0110_RAW2SCAN(key) | M0110_KEYPAD_OFFSET); - } - } else { - // Shift + other keys - keybuf = M0110_RAW2SCAN(key2); - return M0110_RAW2SCAN(key); - } - break; - default: - // other keys - return M0110_RAW2SCAN(key); - break; - } -} - - -static inline uint8_t inquiry(void) -{ - m0110_send(M0110_INQUIRY); - return m0110_recv(); -} - -static inline uint8_t instant(void) -{ - m0110_send(M0110_INSTANT); - return m0110_recv(); -} - -static inline void clock_lo() -{ - M0110_CLOCK_PORT &= ~(1<>1)) \ - ) \ - ) \ -) - extern uint8_t m0110_error; diff --git a/m0110_usb/doc/m0110.jpg b/m0110_usb/doc/m0110.jpg old mode 100755 new mode 100644 diff --git a/m0110_usb/doc/teensy.jpg b/m0110_usb/doc/teensy.jpg old mode 100755 new mode 100644 diff --git a/m0110_usb/keymap.c b/m0110_usb/keymap.c index 8c509a59..c6b7cbd3 100644 --- a/m0110_usb/keymap.c +++ b/m0110_usb/keymap.c @@ -58,7 +58,7 @@ static const uint8_t PROGMEM fn_layer[] = { 1, // Fn0 2, // Fn1 3, // Fn2 - 0, // Fn3 + 1, // Fn3 0, // Fn4 0, // Fn5 0, // Fn6 @@ -68,15 +68,17 @@ static const uint8_t PROGMEM fn_layer[] = { // 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[] = { +#ifndef HASU KB_ESC, // Fn0 -#ifdef HASU - KB_SCOLON, // Fn1 - KB_SLASH, // Fn2 -#else KB_NO, // Fn1 KB_NO, // Fn2 -#endif KB_NO, // Fn3 +#else + KB_NO, // Fn0 + KB_SCOLON, // Fn1 + KB_SLASH, // Fn2 + KB_UP, // Fn3 +#endif KB_NO, // Fn4 KB_NO, // Fn5 KB_NO, // Fn6 @@ -107,7 +109,6 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |---------------------------------------------------------| |-----------|Ent| * |Ctrl |Alt | Space |Gui| \|Lft|Rgt|Dn | | 0| .| | * `---------------------------------------------------------' `---------------' - * You can register Esc by hitting(press&release) Fn0 quickly. * * HHKB/WASD cursor Layer(Fn0): * ,---------------------------------------------------------. ,---------------. @@ -122,49 +123,18 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |Ctrl |Alt | Space |Gui | \|Lft|Rgt|Dn | | 0| .| | * `---------------------------------------------------------' `---------------' * - * NOTE: Key between Space and \ in above diagram is M0110 Enter(assigned to Gui). + * NOTE: You can register Esc by hitting(press&release) Fn0 quickly. + * NOTE: Gui between Space and \ is Enter on M0110 not exists on M0110A. * NOTE: LShift and RShift are logically same key. (M0110, M0110A) * NOTE: LOption and ROption are logically same key. (M0110) */ -#ifdef HASU - KEYMAP( - ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, ESC, PEQL,PSLS,PAST, - TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS, - LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT, ENT, P4, P5, P6, PPLS, - LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, UP, P1, P2, P3, PENT, - FN0, LALT, SPC, LGUI,BSLS,LEFT,DOWN,RGHT, P0, PDOT - ), - // HHKB & WASD - KEYMAP( - GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,PEQL,PSLS,PAST, - CAPS,HOME,UP, PGUP,NO, NO, NO, NO, PSCR,SLCK,BRK, UP, INS, P7, P8, P9, PMNS, - LCTL,LEFT,DOWN,RGHT,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT, ENT, P4, P5, P6, PPLS, - LSFT,END, NO, PGDN,NO, VOLD,VOLU,MUTE,END, PGDN,DOWN, UP, P1, P2, P3, PENT, - FN0, LALT, SPC, LGUI,BSLS,LEFT,DOWN,RGHT, P0, PDOT - ), - // vi mousekeys - KEYMAP( - GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,PEQL,PSLS,PAST, - CAPS,NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, P7, P8, P9, PMNS, - NO, VOLD,VOLU,MUTE,NO, NO, MS_L,MS_D,MS_U,MS_R,FN1, NO, ENT, P4, P5, P6, PPLS, - LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,NO, NO, NO, UP, P1, P2, P3, PENT, - LCTL,LALT, BTN1, LGUI,BSLS,LEFT,DOWN,RGHT, P0, PDOT - ), - // vi cusorkeys - KEYMAP( - GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,PEQL,PSLS,PAST, - CAPS,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, P7, P8, P9, PMNS, - NO, NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, - LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, UP, P1, P2, P3, PENT, - LCTL,LALT, SPC, LGUI,BSLS,LEFT,DOWN,RGHT, P0, PDOT - ), -#else +#ifndef HASU KEYMAP( GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, LGUI,PEQL,PSLS,PAST, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS, FN0, A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, UP, P1, P2, P3, PENT, - LCTL,LALT, SPC, LGUI,BSLS,LEFT,DOWN,RGHT, P0, PDOT + LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT ), // HHKB & WASD KEYMAP( @@ -172,7 +142,41 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { CAPS,HOME,UP, PGUP,NO, NO, NO, NO, PSCR,SLCK,BRK, UP, INS, P7, P8, P9, PMNS, FN0, LEFT,DOWN,RGHT,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT, ENT, P4, P5, P6, PPLS, LSFT,END, NO, PGDN,NO, VOLD,VOLU,MUTE,END, PGDN,DOWN, UP, P1, P2, P3, PENT, - LCTL,LALT, SPC, LGUI,BSLS,LEFT,DOWN,RGHT, P0, PDOT + LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT + ), +#else + // hasu's keymap + // To enable use this 'make' option: make EXTRAFLAGS=-DHASU + KEYMAP( + ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, ESC, PEQL,PSLS,PAST, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS, + LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, FN3, P1, P2, P3, PENT, + LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT + ), + // HHKB & WASD + KEYMAP( + GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,PEQL,PSLS,PAST, + CAPS,HOME,UP, PGUP,NO, NO, NO, NO, PSCR,SLCK,BRK, UP, INS, P7, P8, P9, PMNS, + LCTL,LEFT,DOWN,RGHT,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT, ENT, P4, P5, P6, PPLS, + LSFT,END, NO, PGDN,NO, VOLD,VOLU,MUTE,END, PGDN,DOWN, FN3, P1, P2, P3, PENT, + LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT + ), + // vi mousekeys + KEYMAP( + GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,PEQL,PSLS,PAST, + CAPS,NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, P7, P8, P9, PMNS, + NO, VOLD,VOLU,MUTE,NO, NO, MS_L,MS_D,MS_U,MS_R,FN1, NO, ENT, P4, P5, P6, PPLS, + LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,NO, NO, NO, UP, P1, P2, P3, PENT, + LCTL,LALT, BTN1, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT + ), + // vi cusorkeys + KEYMAP( + GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,PEQL,PSLS,PAST, + CAPS,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, P7, P8, P9, PMNS, + NO, NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, + LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, UP, P1, P2, P3, PENT, + LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT ), #endif }; diff --git a/m0110_usb/matrix.c b/m0110_usb/matrix.c index 11303ee0..b28045b9 100644 --- a/m0110_usb/matrix.c +++ b/m0110_usb/matrix.c @@ -32,10 +32,15 @@ along with this program. If not, see . #define CAPS 0x39 -#define CAPS_UP (CAPS | 0x80) +#define CAPS_BREAK (CAPS | 0x80) #define ROW(key) ((key)>>3&0x0F) #define COL(key) ((key)&0x07) +#define ARROW_UP_BREAK (0x4D | 0x80) +#define ARROW_DOWN_BREAK (0x48 | 0x80) +#define ARROW_LEFT_BREAK (0x46 | 0x80) +#define ARROW_RIGHT_BREAK (0x42 | 0x80) + static bool is_modified = false; @@ -88,14 +93,27 @@ uint8_t matrix_scan(void) // Send Caps key up event if (matrix_is_on(ROW(CAPS), COL(CAPS))) { is_modified = true; - register_key(CAPS_UP); + register_key(CAPS_BREAK); } #endif if (key == M0110_NULL) { return 0; } else if (key == M0110_ERROR) { - // TODO: error recovery or reinit return 0; + } else if (key == ARROW_UP_BREAK || + key == ARROW_DOWN_BREAK || + key == ARROW_LEFT_BREAK || + key == ARROW_RIGHT_BREAK) { + // WORK AROUND: exceptional handling for M0110A + // Unregister both Arrow key and coressponding Calc key when receive Arrow key break. + // + // Shift + Calc keys(=/*+): + // Send no Shift break(0xF1) when release Calc keys. Can't be desinguished from Arrow keys. + // (press: 0x71, 0x79, 0xXX release: 0x79, 0xXX) + // See m0110.c for key events and scan codes. + is_modified = true; + register_key(key); + register_key(key|M0110_CALC_OFFSET); } else { #ifdef MATRIX_HAS_LOCKING_CAPS if (host_keyboard_leds() & (1<