]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - ps2_usb/matrix.c
added copyright and license notice.
[max/tmk_keyboard.git] / ps2_usb / matrix.c
index 366568d681f3f51f84eb5c1992b7b3b7d43fe9b2..5d73cc2a3b196b7e6d88e3f922af5335b28d9efc 100644 (file)
@@ -1,3 +1,20 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 /*
  * scan matrix
  */
@@ -9,8 +26,7 @@
 #include "util.h"
 #include "debug.h"
 #include "ps2.h"
-#include "usb_keyboard.h"
-#include "matrix_skel.h"
+#include "matrix.h"
 
 
 #if (MATRIX_COLS > 16)
  *      8bit
  *    ---------
  *  0|         |
- *  :|   XX    | 00-7F for normal codes
+ *  :|   XX    | 00-7F for normal codes(without E0-prefix)
  *  f|_________|
  * 10|         |
  *  :|  E0 XX  | 80-FF for E0-prefix codes(use (XX|0x80) as code)
  * 1f|         |
  *    ---------
  * exceptions:
- * 0x83: F8(normal code placed beyond 0x7F)
- * 0xFE: PrintScreen
- * 0xFF: Puause/Break
+ * 83:    F8[0x83](normal codes but > 0x7F)
+ * FC:    PrintScreen[E0 7C or 84]
+ * FE:    Puause
  */
-#define _PRINT_SCREEN   (0xFE)
-#define _PAUSE_BREAK    (0xFF)
-#define _ROW(code)      (code>>3)
-#define _COL(code)      (code&0x07)
+#define F8             (0x83)
+#define PRINT_SCREEN   (0xFC)
+#define PAUSE          (0xFE)
+#define ROW(code)      (code>>3)
+#define COL(code)      (code&0x07)
 
-static bool _matrix_is_modified = false;
+static bool is_modified = false;
 
 // matrix state buffer(1:on, 0:off)
 #if (MATRIX_COLS <= 8)
-static uint8_t *matrix;
-static uint8_t _matrix0[MATRIX_ROWS];
+static uint8_t matrix[MATRIX_ROWS];
 #else
-static uint16_t *matrix;
-static uint16_t _matrix0[MATRIX_ROWS];
+static uint16_t matrix[MATRIX_ROWS];
 #endif
 
 #ifdef MATRIX_HAS_GHOST
 static bool matrix_has_ghost_in_row(uint8_t row);
 #endif
-static void _matrix_make(uint8_t code);
-static void _matrix_break(uint8_t code);
-static void _ps2_reset(void);
-static void _ps2_set_leds(uint8_t leds);
+static void matrix_make(uint8_t code);
+static void matrix_break(uint8_t code);
 
 
 inline
@@ -79,41 +92,87 @@ uint8_t matrix_cols(void)
 
 void matrix_init(void)
 {
-    print_enable = true;
     ps2_host_init();
 
-    _ps2_reset();
-
-    // flush LEDs
-    _ps2_set_leds(1<<PS2_LED_NUM_LOCK);
-    _delay_ms(100);
-    _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK);
-    _delay_ms(100);
-    _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK);
-    _delay_ms(300);
-    _ps2_set_leds(0x00);
-    
     // initialize matrix state: all keys off
-    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
-    matrix = _matrix0;
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
 
     return;
 }
 
+/*
+ * PS/2 Scan Code Set 2: Exceptional Handling
+ *
+ * There are several keys to be handled exceptionally.
+ * The scan code for these keys are varied or prefix/postfix'd
+ * depending on modifier key state.
+ *
+ * References:
+ *     http://www.microsoft.com/whdc/archive/scancode.mspx
+ *     http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
+ *
+ *
+ * Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left:
+ *     Num Lock: off
+ *     modifiers | make                      | break
+ *     ----------+---------------------------+----------------------
+ *     Ohter     |                    <make> | <break>
+ *     LShift    | E0 F0 12           <make> | <break>  E0 12
+ *     RShift    | E0 F0 59           <make> | <break>  E0 59
+ *     L+RShift  | E0 F0 12  E0 F0 59 <make> | <break>  E0 59 E0 12
+ *
+ *     Num Lock: on
+ *     modifiers | make                      | break
+ *     ----------+---------------------------+----------------------
+ *     Other     | E0 12              <make> | <break>  E0 F0 12
+ *     Shift'd   |                    <make> | <break>
+ *
+ *     Handling: ignore these prefix/postfix codes
+ *
+ *
+ * Keypad-/:
+ *     modifiers | make                      | break
+ *     ----------+---------------------------+----------------------
+ *     Ohter     |                    <make> | <break>
+ *     LShift    | E0 F0 12           <make> | <break>  E0 12
+ *     RShift    | E0 F0 59           <make> | <break>  E0 59
+ *     L+RShift  | E0 F0 12  E0 F0 59 <make> | <break>  E0 59 E0 12
+ *
+ *     Handling: ignore these prefix/postfix codes
+ *
+ *
+ * PrintScreen:
+ *     With hoding down modifiers, the scan code is sent as following:
+ *
+ *     modifiers | make         | break
+ *     ----------+--------------+-----------------------------------
+ *     Other     | E0 12  E0 7C | E0 F0 7C  E0 F0 12
+ *     Shift'd   |        E0 7C | E0 F0 7C
+ *     Control'd |        E0 7C | E0 F0 7C
+ *     Alt'd     |           84 | F0 84
+ *
+ *     Handling: ignore prefix/postfix codes and treat both scan code
+ *               E0 7C and 84 as PrintScreen.
+ *
+ * Pause:
+ *     With hoding down modifiers, the scan code is sent as following:
+ *
+ *     modifiers | make(no break code)
+ *     ----------+--------------------------------------------------
+ *     no mods   | E1 14 77 E1 F0 14 F0 77
+ *     Control'd | E0 7E E0 F0 7E
+ *
+ *     Handling: treat these two code sequence as Pause
+ *
+ */
 uint8_t matrix_scan(void)
 {
 
     static enum {
         INIT,
-        BREAK,
+        F0,
         E0,
         E0_F0,
-        // states for PrintScreen
-        E0_12,
-        E0_12_E0,
-        E0_F0_7C,
-        E0_F0_7C_E0,
-        E0_F0_7C_E0_F0,
         // states for Pause/Break
         E1,
         E1_14,
@@ -125,11 +184,11 @@ uint8_t matrix_scan(void)
     } state = INIT;
 
 
-    _matrix_is_modified = false;
+    is_modified = false;
 
     // Pause/Break off(PS/2 has no break for this key)
-    if (matrix_is_on(_ROW(_PAUSE_BREAK), _COL(_PAUSE_BREAK))) {
-        _matrix_break(_PAUSE_BREAK);
+    if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
+        matrix_break(PAUSE);
     }
 
     uint8_t code;
@@ -141,113 +200,88 @@ uint8_t matrix_scan(void)
                         state = E0;
                         break;
                     case 0xF0:  // break code
-                        state = BREAK;
+                        state = F0;
                         break;
                     case 0xE1:  // Pause/Break
                         state = E1;
                         break;
+                    case 0x83:  // F8
+                        matrix_make(F8);
+                        state = INIT;
+                        break;
+                    case 0x84:  // PrintScreen
+                        matrix_make(PRINT_SCREEN);
+                        state = INIT;
+                        break;
                     default:    // normal key make
                         if (code < 0x80) {
-                            _matrix_make(code);
+                            matrix_make(code);
                         } else {
-                            debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
+                            debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n");
                         }
                         state = INIT;
                 }
                 break;
             case E0:
                 switch (code) {
-                    case 0x12:  // PrintScreen(make)
-                        state = E0_12;
-                        break;
-                    case 0x7C:  // PrintScreen(typematic)
+                    case 0x12:  // postfix/postfix code for exceptional keys
+                    case 0x59:  // postfix/postfix code for exceptional keys
                         // ignore
                         state = INIT;
                         break;
+                    case 0x7E:  // former part of Control-Pause[E0 7E  E0 F0 7E]
+                        matrix_make(PAUSE);
+                        state = INIT;
+                        break;
                     case 0xF0:  // E0 break
                         state = E0_F0;
                         break;
                     default:    // E0 make
                         if (code < 0x80) {
-                            _matrix_make(code|0x80);
-                        } else {
-                            debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
-                        }
-                        state = INIT;
-                }
-                break;
-            case BREAK:
-                if (code < 0x80) {
-                    _matrix_break(code);
-                } else {
-                    debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
-                }
-                state = INIT;
-                break;
-            case E0_F0: // E0 break
-                switch (code) {
-                    case 0x7C:
-                        state = E0_F0_7C;
-                        break;
-                    default:
-                        if (code < 0x80) {
-                            _matrix_break(code|0x80);
+                            matrix_make(code|0x80);
                         } else {
-                            debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
+                            debug("unexpected scan code at E0: "); debug_hex(code); debug("\n");
                         }
                         state = INIT;
                 }
                 break;
-            /* PrintScreen(make) */
-            case E0_12:
+            case F0:
                 switch (code) {
-                    case 0xE0:
-                        state = E0_12_E0;
-                        break;
-                    default:
-                        state = INIT;
-                }
-                break;
-            case E0_12_E0:
-                switch (code) {
-                    case 0x7C:
-                        _matrix_make(_PRINT_SCREEN);
+                    case 0x83:
+                        matrix_break(F8);
                         state = INIT;
                         break;
-                    default:
-                        state = INIT;
-                }
-                break;
-            /* PrintScreen(break) */
-            case E0_F0_7C:
-                switch (code) {
-                    case 0xE0:
-                        state = E0_F0_7C_E0;
-                        break;
-                    default:
+                    case 0x84:
+                        matrix_break(PRINT_SCREEN);
                         state = INIT;
-                }
-                break;
-            case E0_F0_7C_E0:
-                switch (code) {
-                    case 0xF0:
-                        state = E0_F0_7C_E0_F0;
                         break;
                     default:
-                        state = INIT;
+                    if (code < 0x80) {
+                        matrix_break(code);
+                    } else {
+                        debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
+                    }
+                    state = INIT;
                 }
                 break;
-            case E0_F0_7C_E0_F0:
+            case E0_F0: // E0 break
                 switch (code) {
-                    case 0x12:
-                        _matrix_break(_PRINT_SCREEN);
+                    case 0x12:  // postfix/postfix code for exceptional keys
+                    case 0x59:  // postfix/postfix code for exceptional keys
+                    case 0x7E:  // latter part of Control-Pause[E0 7E  E0 F0 7E]
+                        // ignore
                         state = INIT;
                         break;
                     default:
+                        if (code < 0x80) {
+                            matrix_break(code|0x80);
+                        } else {
+                            debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n");
+                        }
                         state = INIT;
                 }
                 break;
-            /* Pause/Break */
+            /* Pause */
             case E1:
                 switch (code) {
                     case 0x14:
@@ -305,7 +339,7 @@ uint8_t matrix_scan(void)
             case E1_14_77_E1_F0_14_F0:
                 switch (code) {
                     case 0x77:
-                        _matrix_make(_PAUSE_BREAK);
+                        matrix_make(PAUSE);
                         state = INIT;
                         break;
                     default:
@@ -316,27 +350,12 @@ uint8_t matrix_scan(void)
                 state = INIT;
         }
     }
-
-    static uint8_t prev_leds = 0;
-    if (prev_leds != usb_keyboard_leds) {
-        uint8_t leds = 0;
-        if (usb_keyboard_leds&(1<<USB_LED_SCROLL_LOCK))
-            leds |= (1<<PS2_LED_SCROLL_LOCK);
-        if (usb_keyboard_leds&(1<<USB_LED_NUM_LOCK))
-            leds |= (1<<PS2_LED_NUM_LOCK);
-        if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK))
-            leds |= (1<<PS2_LED_CAPS_LOCK);
-
-        _ps2_set_leds(leds);
-        prev_leds = usb_keyboard_leds;
-    }
-
     return 1;
 }
 
 bool matrix_is_modified(void)
 {
-    return _matrix_is_modified;
+    return is_modified;
 }
 
 inline
@@ -422,35 +441,19 @@ static bool matrix_has_ghost_in_row(uint8_t row)
 
 
 inline
-static void _matrix_make(uint8_t code)
+static void matrix_make(uint8_t code)
 {
-    if (!matrix_is_on(_ROW(code), _COL(code))) {
-        matrix[_ROW(code)] |= 1<<_COL(code);
-        _matrix_is_modified = true;
+    if (!matrix_is_on(ROW(code), COL(code))) {
+        matrix[ROW(code)] |= 1<<COL(code);
+        is_modified = true;
     }
 }
 
 inline
-static void _matrix_break(uint8_t code)
+static void matrix_break(uint8_t code)
 {
-    if (matrix_is_on(_ROW(code), _COL(code))) {
-        matrix[_ROW(code)] &= ~(1<<_COL(code));
-        _matrix_is_modified = true;
+    if (matrix_is_on(ROW(code), COL(code))) {
+        matrix[ROW(code)] &= ~(1<<COL(code));
+        is_modified = true;
     }
 }
-
-static void _ps2_reset(void)
-{
-    ps2_host_send(0xFF);
-    ps2_host_recv(); // 0xFA
-    ps2_host_recv(); // 0xAA
-    _delay_ms(1000);
-}
-
-static void _ps2_set_leds(uint8_t leds)
-{
-        ps2_host_send(0xED);
-        ps2_host_recv();        // 0xFA
-        ps2_host_send(leds);
-        ps2_host_recv();        // 0xFA
-}